Full Code of codecentric/hikaku for AI

master b8a754f91b52 cached
305 files
793.0 KB
158.9k tokens
1 requests
Download .txt
Showing preview only (906K chars total). Download the full file or copy to clipboard to get everything.
Repository: codecentric/hikaku
Branch: master
Commit: b8a754f91b52
Files: 305
Total size: 793.0 KB

Directory structure:
gitextract_0lqdq178/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── feature_request.md
│   │   └── question.md
│   └── dependabot.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.gradle
├── core/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               ├── Hikaku.kt
│       │   │               ├── HikakuConfig.kt
│       │   │               ├── SupportedFeatures.kt
│       │   │               ├── converters/
│       │   │               │   ├── AbstractEndpointConverter.kt
│       │   │               │   ├── ClassLocator.kt
│       │   │               │   ├── EndpointConverter.kt
│       │   │               │   └── EndpointConverterException.kt
│       │   │               ├── endpoints/
│       │   │               │   ├── Endpoint.kt
│       │   │               │   ├── HeaderParameter.kt
│       │   │               │   ├── HttpMethod.kt
│       │   │               │   ├── MatrixParameter.kt
│       │   │               │   ├── PathParameter.kt
│       │   │               │   └── QueryParameter.kt
│       │   │               ├── extensions/
│       │   │               │   ├── ClassExtensions.kt
│       │   │               │   ├── FileExtensions.kt
│       │   │               │   └── PathExtensions.kt
│       │   │               └── reporters/
│       │   │                   ├── CommandLineReporter.kt
│       │   │                   ├── MatchResult.kt
│       │   │                   ├── NoOperationReporter.kt
│       │   │                   └── Reporter.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   └── de/
│           │       └── codecentric/
│           │           └── hikaku/
│           │               ├── HikakuTest.kt
│           │               └── extensions/
│           │                   ├── ClassExtensionsTest.kt
│           │                   ├── FileExtensionsTest.kt
│           │                   └── PathExtensionsTest.kt
│           └── resources/
│               └── test_file.txt
├── docs/
│   ├── config.md
│   └── features.md
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── install-jdk.sh
├── jax-rs/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── jaxrs/
│       │   │                       └── JaxRsConverter.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   ├── de/
│           │   │   └── codecentric/
│           │   │       └── hikaku/
│           │   │           └── converters/
│           │   │               └── jaxrs/
│           │   │                   ├── JaxRsConverterConsumesTest.kt
│           │   │                   ├── JaxRsConverterDeprecationTest.kt
│           │   │                   ├── JaxRsConverterHeaderParametersTest.kt
│           │   │                   ├── JaxRsConverterHttpMethodsTest.kt
│           │   │                   ├── JaxRsConverterMatrixParametersTest.kt
│           │   │                   ├── JaxRsConverterPackageDefinitionTest.kt
│           │   │                   ├── JaxRsConverterPathParametersTest.kt
│           │   │                   ├── JaxRsConverterPathTests.kt
│           │   │                   ├── JaxRsConverterProducesTest.kt
│           │   │                   └── JaxRsConverterQueryParameterTest.kt
│           │   └── test/
│           │       └── jaxrs/
│           │           ├── consumes/
│           │           │   ├── functiondeclarationoverwritesclassdeclaration/
│           │           │   │   └── FunctionDeclarationOverwritesClassDeclaration.kt
│           │           │   ├── multiplemediatypesonclass/
│           │           │   │   └── MultipleMediaTypesOnClass.kt
│           │           │   ├── multiplemediatypesonfunction/
│           │           │   │   └── MultipleMediaTypesOnFunction.kt
│           │           │   ├── noannotation/
│           │           │   │   └── NoAnnotation.kt
│           │           │   ├── singlemediatypeonclass/
│           │           │   │   └── ProducesOnClass.kt
│           │           │   ├── singlemediatypeonfunction/
│           │           │   │   └── ProducesOnFunction.kt
│           │           │   ├── singlemediatypewithoutrequestbody/
│           │           │   │   └── SingleMediaTypeWithoutRequestBody.kt
│           │           │   └── singlemediatypewithoutrequestbodybutotherannotatedparameter/
│           │           │       └── SingleMediaTypeWithoutRequestBodyButOtherAnnotatedParameter.kt
│           │           ├── deprecation/
│           │           │   ├── none/
│           │           │   │   └── NoDeprecation.kt
│           │           │   ├── onclass/
│           │           │   │   └── DeprecationOnClass.kt
│           │           │   └── onfunction/
│           │           │       └── DeprecationOnFunction.kt
│           │           ├── headerparameters/
│           │           │   └── onfunction/
│           │           │       └── HeaderParametersOnFunction.kt
│           │           ├── httpmethod/
│           │           │   ├── allmethods/
│           │           │   │   └── AllHttpMethods.kt
│           │           │   └── noannotation/
│           │           │       └── NoAnnotation.kt
│           │           ├── matrixparameters/
│           │           │   └── onfunction/
│           │           │       └── MatrixParametersOnFunction.kt
│           │           ├── path/
│           │           │   ├── nestedpath/
│           │           │   │   └── NestedPath.kt
│           │           │   ├── nestedpathwithoutleadingslash/
│           │           │   │   └── NestedPathWithoutLeadingSlash.kt
│           │           │   ├── nopathonclass/
│           │           │   │   └── NoPathAnnotationOnclass.kt
│           │           │   ├── simplepath/
│           │           │   │   └── SimplePath.kt
│           │           │   └── simplepathwithoutleadingslash/
│           │           │       └── SimplePathWithoutLeadingSlash.kt
│           │           ├── pathparameters/
│           │           │   ├── nopathparameter/
│           │           │   │   └── NoPathParameter.kt
│           │           │   └── onfunction/
│           │           │       └── PathParameterOnFunction.kt
│           │           ├── produces/
│           │           │   ├── functiondeclarationoverwritesclassdeclaration/
│           │           │   │   └── FunctionDeclarationOverwritesClassDeclaration.kt
│           │           │   ├── multiplemediatypesonclass/
│           │           │   │   └── MultipleMediaTypesOnClass.kt
│           │           │   ├── multiplemediatypesonfunction/
│           │           │   │   └── MultipleMediaTypesOnFunction.kt
│           │           │   ├── noannotation/
│           │           │   │   └── NoAnnotation.kt
│           │           │   ├── singlemediatypeonclass/
│           │           │   │   └── ProducesOnClass.kt
│           │           │   ├── singlemediatypeonfunction/
│           │           │   │   └── ProducesOnFunction.kt
│           │           │   └── singlemediatypewithoutreturntype/
│           │           │       └── SingleMediaTypeWithoutReturnType.kt
│           │           └── queryparameters/
│           │               └── onfunction/
│           │                   └── QueryParameterOnFunction.kt
│           └── resources/
│               └── .gitemptydir
├── micronaut/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── micronaut/
│       │   │                       └── MicronautConverter.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   ├── de/
│           │   │   └── codecentric/
│           │   │       └── hikaku/
│           │   │           └── converters/
│           │   │               └── micronaut/
│           │   │                   ├── MicronautConverterConsumesTest.kt
│           │   │                   ├── MicronautConverterDeprecationTest.kt
│           │   │                   ├── MicronautConverterHeaderParameterTest.kt
│           │   │                   ├── MicronautConverterPackageDefinitionTest.kt
│           │   │                   ├── MicronautConverterPathParameterTest.kt
│           │   │                   ├── MicronautConverterPathTest.kt
│           │   │                   ├── MicronautConverterProducesTest.kt
│           │   │                   └── MicronautConverterQueryParameterTest.kt
│           │   └── test/
│           │       └── micronaut/
│           │           ├── Todo.kt
│           │           ├── consumes/
│           │           │   ├── default/
│           │           │   │   └── ConsumesDefaultMediaTypeTestController.kt
│           │           │   ├── onclass/
│           │           │   │   ├── consumesoverridescontroller/
│           │           │   │   │   ├── multiplemediatypes/
│           │           │   │   │   │   └── ConsumesMultipleMediaTypesTestController.kt
│           │           │   │   │   └── singlemediatype/
│           │           │   │   │       └── ConsumesSingleMediaTypeTestController.kt
│           │           │   │   └── onlycontroller/
│           │           │   │       ├── multiplemediatypes/
│           │           │   │       │   └── ConsumesMultipleMediaTypesTestController.kt
│           │           │   │       └── singlemediatype/
│           │           │   │           └── ConsumesSingleMediaTypeTestController.kt
│           │           │   └── onfunction/
│           │           │       ├── consumesoverridescontroller/
│           │           │       │   ├── multiplemediatypes/
│           │           │       │   │   └── ConsumesMultipleMediaTypesTestController.kt
│           │           │       │   └── singlemediatype/
│           │           │       │       └── ConsumesSingleMediaTypeTestController.kt
│           │           │       └── onlyconsumes/
│           │           │           ├── multiplemediatypes/
│           │           │           │   └── ConsumesMultipleMediaTypesTestController.kt
│           │           │           └── singlemediatype/
│           │           │               └── ConsumesSingleMediaTypeTestController.kt
│           │           ├── deprecation/
│           │           │   ├── none/
│           │           │   │   └── NoDeprecation.kt
│           │           │   ├── onclass/
│           │           │   │   └── DeprecationOnClass.kt
│           │           │   └── onfunction/
│           │           │       └── DeprecationOnFunction.kt
│           │           ├── headerparameters/
│           │           │   ├── optional/
│           │           │   │   └── HeaderParameterTestController.kt
│           │           │   └── required/
│           │           │       └── HeaderParameterTestController.kt
│           │           ├── path/
│           │           │   ├── combinedcontrollerandhttpmethodannotation/
│           │           │   │   ├── delete/
│           │           │   │   │   └── CombinedControllerAnnotationWithDeletePathTestController.kt
│           │           │   │   ├── get/
│           │           │   │   │   └── CombinedControllerAnnotationWithGetPathTestController.kt
│           │           │   │   ├── head/
│           │           │   │   │   └── CombinedControllerAnnotationWithHeadPathTestController.kt
│           │           │   │   ├── options/
│           │           │   │   │   └── CombinedControllerAnnotationWithOptionsPathTestController.kt
│           │           │   │   ├── patch/
│           │           │   │   │   └── CombinedControllerAnnotationWithPatchPathTestController.kt
│           │           │   │   ├── post/
│           │           │   │   │   └── CombinedControllerAnnotationWithPostPathTestController.kt
│           │           │   │   └── put/
│           │           │   │       └── CombinedControllerAnnotationWithPutPathTestController.kt
│           │           │   ├── firstpathsegmentwithoutleadingslash/
│           │           │   │   └── FirstPathSegmentWithoutLeadingSlashTestController.kt
│           │           │   ├── innerpathsegmentwithoutleadingslash/
│           │           │   │   └── InnerPathSegmentWithoutLeadingSlashTestController.kt
│           │           │   ├── nohttpmethodannotation/
│           │           │   │   └── NoHttpMethodAnnotationTestController.kt
│           │           │   └── onlycontrollerannotation/
│           │           │       ├── delete/
│           │           │       │   └── OnlyControllerAnnotationWithDeletePathTestController.kt
│           │           │       ├── get/
│           │           │       │   └── OnlyControllerAnnotationWithGetPathTestController.kt
│           │           │       ├── head/
│           │           │       │   └── OnlyControllerAnnotationWithHeadPathTestController.kt
│           │           │       ├── options/
│           │           │       │   └── OnlyControllerAnnotationWithOptionsPathTestController.kt
│           │           │       ├── patch/
│           │           │       │   └── OnlyControllerAnnotationWithPatchPathTestController.kt
│           │           │       ├── post/
│           │           │       │   └── OnlyControllerAnnotationWithPostPathTestController.kt
│           │           │       └── put/
│           │           │           └── OnlyControllerAnnotationWithPutPathTestController.kt
│           │           ├── pathparameters/
│           │           │   ├── annotation/
│           │           │   │   ├── name/
│           │           │   │   │   └── PathParameterDefinedByAnnotationTestController.kt
│           │           │   │   └── value/
│           │           │   │       └── PathParameterDefinedByAnnotationTestController.kt
│           │           │   └── variable/
│           │           │       └── PathParameterDefinedByVariableNameTestController.kt
│           │           ├── produces/
│           │           │   ├── default/
│           │           │   │   └── DefaultTestController.kt
│           │           │   ├── onclass/
│           │           │   │   ├── onlycontroller/
│           │           │   │   │   ├── multiplemediatypes/
│           │           │   │   │   │   └── ProducesMultipleMediaTypesTestController.kt
│           │           │   │   │   └── singlemediatype/
│           │           │   │   │       └── ProducesSingleMediaTypeTestController.kt
│           │           │   │   └── producesoverridescontroller/
│           │           │   │       ├── multiplemediatypes/
│           │           │   │       │   └── ProducesMultipleMediaTypesTestController.kt
│           │           │   │       └── singlemediatype/
│           │           │   │           └── ProducesSingleMediaTypeTestController.kt
│           │           │   └── onfunction/
│           │           │       ├── onlyproduces/
│           │           │       │   ├── multiplemediatypes/
│           │           │       │   │   └── ProducesMultipleMediaTypesTestController.kt
│           │           │       │   └── singlemediatype/
│           │           │       │       └── ProducesSingleMediaTypeTestController.kt
│           │           │       └── producesoverridescontroller/
│           │           │           ├── multiplemediatypes/
│           │           │           │   └── ProducesMultipleMediaTypesTestController.kt
│           │           │           └── singlemediatype/
│           │           │               └── ProducesSingleMediaTypeTestController.kt
│           │           └── queryparameters/
│           │               ├── optional/
│           │               │   └── QueryParameterTestController.kt
│           │               └── required/
│           │                   ├── annotation/
│           │                   │   └── QueryParameterTestController.kt
│           │                   └── withoutannotation/
│           │                       └── QueryParameterTestController.kt
│           └── resources/
│               └── resources/
│                   └── .gitemptydir
├── openapi/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── openapi/
│       │   │                       ├── OpenApiConverter.kt
│       │   │                       ├── extensions/
│       │   │                       │   ├── PathItemExtensions.kt
│       │   │                       │   └── ReferencedSchema.kt
│       │   │                       └── extractors/
│       │   │                           ├── ConsumesExtractor.kt
│       │   │                           ├── HeaderParameterExtractor.kt
│       │   │                           ├── PathParameterExtractor.kt
│       │   │                           ├── ProducesExtractor.kt
│       │   │                           └── QueryParameterExtractor.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   └── de/
│           │       └── codecentric/
│           │           └── hikaku/
│           │               └── converters/
│           │                   └── openapi/
│           │                       ├── OpenApiConverterConsumesTest.kt
│           │                       ├── OpenApiConverterDeprecationTest.kt
│           │                       ├── OpenApiConverterEndpointTest.kt
│           │                       ├── OpenApiConverterHeaderParameterTest.kt
│           │                       ├── OpenApiConverterInvalidInputTest.kt
│           │                       ├── OpenApiConverterPathParameterTest.kt
│           │                       ├── OpenApiConverterProducesTest.kt
│           │                       └── OpenApiConverterQueryParameterTest.kt
│           └── resources/
│               ├── consumes/
│               │   ├── consumes_inline.yaml
│               │   └── consumes_requestbody_in_components.yaml
│               ├── deprecation/
│               │   ├── deprecation_none.yaml
│               │   └── deprecation_operation.yaml
│               ├── endpoints/
│               │   ├── endpoints_all_http_methods.yaml
│               │   ├── endpoints_two_different_paths.yaml
│               │   └── endpoints_two_nested_paths.yaml
│               ├── header_parameter/
│               │   ├── common_header_parameter_in_components.yaml
│               │   ├── common_header_parameter_inline.yaml
│               │   ├── header_parameter_in_components.yaml
│               │   └── header_parameter_inline.yaml
│               ├── invalid_input/
│               │   ├── empty_file.yaml
│               │   ├── syntax_error.yaml
│               │   └── whitespaces_only_file.yaml
│               ├── path_parameter/
│               │   ├── common_path_parameter_in_components.yaml
│               │   ├── common_path_parameter_inline.yaml
│               │   ├── path_parameter_in_components.yaml
│               │   └── path_parameter_inline.yaml
│               ├── produces/
│               │   ├── produces_inline.yaml
│               │   ├── produces_no_content_type.yaml
│               │   ├── produces_response_in_components.yaml
│               │   └── produces_with_default.yaml
│               └── query_parameter/
│                   ├── common_query_parameter_in_components.yaml
│                   ├── common_query_parameter_inline.yaml
│                   ├── query_parameter_in_components.yaml
│                   └── query_parameter_inline.yaml
├── raml/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── raml/
│       │   │                       ├── RamlConverter.kt
│       │   │                       └── extensions/
│       │   │                           ├── MethodExtensions.kt
│       │   │                           └── ResourceExtensions.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   └── de/
│           │       └── codecentric/
│           │           └── hikaku/
│           │               └── converters/
│           │                   └── raml/
│           │                       ├── RamlConverterConsumesTest.kt
│           │                       ├── RamlConverterDeprecationTest.kt
│           │                       ├── RamlConverterHeaderParameterTest.kt
│           │                       ├── RamlConverterHttpMethodTest.kt
│           │                       ├── RamlConverterInvalidInputTest.kt
│           │                       ├── RamlConverterPathParameterTest.kt
│           │                       ├── RamlConverterPathTest.kt
│           │                       ├── RamlConverterProducesTest.kt
│           │                       └── RamlConverterQueryParameterTest.kt
│           └── resources/
│               ├── consumes/
│               │   ├── method_declaration_overwrites_default.raml
│               │   ├── multiple_default_media_types.raml
│               │   ├── multiple_method_declarations.raml
│               │   ├── no_media_type.raml
│               │   ├── single_default_media_type.raml
│               │   └── single_method_declaration.raml
│               ├── deprecation/
│               │   ├── none.raml
│               │   ├── on_method.raml
│               │   └── on_resource.raml
│               ├── header_parameter.raml
│               ├── http_method/
│               │   ├── http_methods.raml
│               │   └── path_without_http_method.raml
│               ├── invalid_input/
│               │   ├── different_extension.css
│               │   ├── empty_file.raml
│               │   ├── invalid_raml_version.raml
│               │   ├── syntax_error.raml
│               │   └── whitespaces_only_file.raml
│               ├── path/
│               │   ├── nested_path.raml
│               │   ├── nested_path_single_entry.raml
│               │   └── simple_path.raml
│               ├── path_parameter/
│               │   ├── nested_path_parameter.raml
│               │   └── simple_path_parameter.raml
│               ├── produces/
│               │   ├── method_declaration_overwrites_default.raml
│               │   ├── multiple_default_media_types.raml
│               │   ├── multiple_method_declarations.raml
│               │   ├── no_media_type.raml
│               │   ├── single_default_media_type.raml
│               │   └── single_method_declaration.raml
│               └── query_parameter/
│                   └── query_parameter.raml
├── settings.gradle
├── spring/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── spring/
│       │   │                       ├── SpringConverter.kt
│       │   │                       └── extensions/
│       │   │                           ├── ConsumesExtension.kt
│       │   │                           ├── DeprecationExtension.kt
│       │   │                           ├── HeaderParametersSpringExtension.kt
│       │   │                           ├── HttpMethodsSpringExtension.kt
│       │   │                           ├── MatrixParametersSpringExtension.kt
│       │   │                           ├── PathParametersSpringExtension.kt
│       │   │                           ├── PathsSpringExtension.kt
│       │   │                           ├── ProducesSpringExtension.kt
│       │   │                           └── QueryParametersSpringExtension.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   └── de/
│           │       └── codecentric/
│           │           └── hikaku/
│           │               └── converters/
│           │                   └── spring/
│           │                       ├── consumes/
│           │                       │   ├── ConsumesTestController.kt
│           │                       │   └── SpringConverterConsumesTest.kt
│           │                       ├── deprecation/
│           │                       │   ├── DeprecationTestController.kt
│           │                       │   └── SpringConverterDeprecationTest.kt
│           │                       ├── headerparameters/
│           │                       │   ├── HeaderParameterTestController.kt
│           │                       │   └── SpringConverterHeaderParameterTest.kt
│           │                       ├── httpmethod/
│           │                       │   ├── HttpMethodTestController.kt
│           │                       │   └── SpringConverterHttpMethodTest.kt
│           │                       ├── matrixparameters/
│           │                       │   ├── MatrixParameterTestController.kt
│           │                       │   └── SpringConverterMatrixParameterTest.kt
│           │                       ├── path/
│           │                       │   ├── PathTestController.kt
│           │                       │   └── SpringConverterPathTest.kt
│           │                       ├── pathparameters/
│           │                       │   ├── PathParameterTestController.kt
│           │                       │   └── SpringConverterPathParameterTest.kt
│           │                       ├── produces/
│           │                       │   ├── redirect/
│           │                       │   │   ├── RedirectTestController.kt
│           │                       │   │   └── SpringControllerRedirectTest.kt
│           │                       │   ├── responsebody/
│           │                       │   │   ├── ProducesResponseBodyAnnotationTestController.kt
│           │                       │   │   └── SpringConverterProducesResponseBodyAnnotationTest.kt
│           │                       │   ├── restcontroller/
│           │                       │   │   ├── ProducesRestControllerAnnotationTestController.kt
│           │                       │   │   └── SpringConverterProducesRestControllerAnnotationTest.kt
│           │                       │   └── servletresponse/
│           │                       │       ├── ProducesServletResponseTestController.kt
│           │                       │       └── SpringConverterProducesServletResponseTest.kt
│           │                       └── queryparameters/
│           │                           ├── QueryParameterTestController.kt
│           │                           └── SpringConverterQueryParameterTest.kt
│           └── resources/
│               └── .gitemptydir
└── wadl/
    ├── README.md
    ├── build.gradle
    └── src/
        ├── main/
        │   ├── kotlin/
        │   │   └── de/
        │   │       └── codecentric/
        │   │           └── hikaku/
        │   │               └── converters/
        │   │                   └── wadl/
        │   │                       ├── WadlConverter.kt
        │   │                       └── extensions/
        │   │                           └── NodeExtensions.kt
        │   └── resources/
        │       └── .gitemptydir
        └── test/
            ├── kotlin/
            │   └── de/
            │       └── codecentric/
            │           └── hikaku/
            │               └── converters/
            │                   └── wadl/
            │                       ├── WadlConverterConsumesTest.kt
            │                       ├── WadlConverterEndpointTest.kt
            │                       ├── WadlConverterHeaderParameterTest.kt
            │                       ├── WadlConverterInvalidInputTest.kt
            │                       ├── WadlConverterMatrixParameterTest.kt
            │                       ├── WadlConverterPathParameterTest.kt
            │                       ├── WadlConverterProducesTest.kt
            │                       └── WadlConverterQueryParameterTest.kt
            └── resources/
                ├── consumes/
                │   ├── consumes_media_types_not_taken_from_produces.wadl
                │   ├── consumes_no_media_types.wadl
                │   └── consumes_three_media_types.wadl
                ├── endpoints/
                │   ├── endpoints.wadl
                │   ├── endpoints_two_different_paths.wadl
                │   └── endpoints_two_nested_paths.wadl
                ├── header_parameters.wadl
                ├── invalid_input/
                │   ├── empty_file.wadl
                │   ├── syntax_error.wadl
                │   └── whitespaces_only_file.wadl
                ├── matrix_parameters.wadl
                ├── path_parameters.wadl
                ├── produces/
                │   ├── produces_media_types_not_taken_from_consumes.wadl
                │   ├── produces_no_media_types.wadl
                │   └── produces_three_media_types.wadl
                └── query_parameters.wadl

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve hikaku
title: ''
labels: Bug
assignees: ''

---

# Setup information
**hikaku version:**
**specification converter:** 
**implementation converter:** 
**build tool and version:** `e.g. gradle 5.2.1, maven 3.5.3, ...`
**test framework:** `e.g. junit 4.12, junit 5.4.0, testng 6.14.3...`

# Describe the bug
A clear and concise description of what the bug is.

# Expected behavior
A clear and concise description of what you expected to happen.

# Code samples
Can you provide specification snippets or code snippets?
```
CODE HERE
```


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for hikaku
title: ''
labels: Feature Request
assignees: ''

---

**Is your feature request related to one or multiple existing converters?**
If related to converters, please list affected converters here.

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Additional context**
Add any other context, examples, snippets, links.


================================================
FILE: .github/ISSUE_TEMPLATE/question.md
================================================
---
name: Question
about: Got a question about hikaku for us?
title: ''
labels: Question
assignees: ''

---




================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "gradle"
    directory: "/"
    schedule:
      interval: "daily"


================================================
FILE: .gitignore
================================================
# Custom

**/out/


# Created by https://www.gitignore.io/api/linux,macos,gradle,kotlin,windows,intellij,intellij+iml,intellij+all

### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries

# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml

# Gradle:
.idea/**/gradle.xml
.idea/**/libraries

# CMake
cmake-build-debug/

# Mongo Explorer plugin:
.idea/**/mongoSettings.xml

## File-based project format:
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Ruby plugin and RubyMine
/.rakeTasks

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721

# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr

# Sonarlint plugin
.idea/sonarlint

### Intellij+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff:

# Sensitive or high-churn files:

# Gradle:

# CMake

# Mongo Explorer plugin:

## File-based project format:

## Plugin-specific files:

# IntelliJ

# mpeltonen/sbt-idea plugin

# JIRA plugin

# Cursive Clojure plugin

# Ruby plugin and RubyMine

# Crashlytics plugin (for Android Studio and IntelliJ)

### Intellij+all Patch ###
# Ignores the whole .idea folder and all .iml files
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360

.idea/

# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023

*.iml
modules.xml
.idea/misc.xml
*.ipr

### Intellij+iml ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff:

# Sensitive or high-churn files:

# Gradle:

# CMake

# Mongo Explorer plugin:

## File-based project format:

## Plugin-specific files:

# IntelliJ

# mpeltonen/sbt-idea plugin

# JIRA plugin

# Cursive Clojure plugin

# Ruby plugin and RubyMine

# Crashlytics plugin (for Android Studio and IntelliJ)

### Intellij+iml Patch ###
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023


### Kotlin ###
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

### Linux ###
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*

### macOS ###
*.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Windows ###
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

### Gradle ###
.gradle
**/build/

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

# Cache of project
.gradletasknamecache

# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties


# End of https://www.gitignore.io/api/linux,macos,gradle,kotlin,windows,intellij,intellij+iml,intellij+all

================================================
FILE: .travis.yml
================================================
language: bash
matrix:
  include:
    - env: JDK="openjdk@1.11.0-2"
      os: linux
      dist: trusty
    - env: JDK="openjdk@1.11.0-2"
      os: windows
    - env: JDK="openjdk@1.11.0-2"
      os: osx
before_install:
  - source install-jdk.sh
install: true
script:
  - ./gradlew clean test


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
# hikaku
[![Build Status](https://api.travis-ci.org/codecentric/hikaku.svg?branch=master)](https://travis-ci.org/codecentric/hikaku) [![Maven Central Version](https://img.shields.io/maven-central/v/de.codecentric.hikaku/hikaku-core.svg)](https://search.maven.org/search?q=g:de.codecentric.hikaku)

<p align="center">
  <img src="docs/images/hikaku-logo-small.png">
</p>

Hikaku (比較) is japanese and means "comparison". This library tests if a REST-API implementation meets its specification.

If you create your REST-API contract-first without using any type of generation, you have to make sure that specification and implementation don't diverge.
The aim of this project is to meet this need and offer a mechanism to check specification and implementation for equality without having to create requests which are fired against a mock server. So this library won't check the behavior of the API, but the structural correctness. Please see also the section [limitations](#limitations)

## Currently supported

+ **Specifications**
  + [OpenAPI 3.0.X](openapi/README.md)
  + [RAML 1.X](raml/README.md)
  + [WADL](wadl/README.md)
+ **Implementations**
  + [Spring MVC 5.3.X](spring/README.md)
  + [Micronaut](micronaut/README.md)
  + [JAX-RS 3.0.X](jax-rs/README.md)
    + [Apache CXF](http://cxf.apache.org)
    + [Dropwizard](https://www.dropwizard.io)
    + [Jersey](https://jersey.github.io)
    + [Resteasy](https://resteasy.github.io)
    + [Restlet](https://restlet.com/open-source/documentation/user-guide/2.3/extensions/jaxrs)
    + [Quarkus](https://quarkus.io)
  
Please refer to the list of [all features](docs/features.md). To check the feature support for each converter.
It is possible that not every converter supports every feature. Only the intersection of the features of two `EndpointConverter`s is used for the matching. Please keep that in mind regarding the equality of implementation and specification.
  
## Usage

Setting up a test with hikaku is very simple. You just instantiate the `Hikaku` class and provide an `EndpointConverter` for the specification and another one for the implementation. Optionally, you can also pass an instance of `HikakuConfig`. Check the list of options and default values of the [config](docs/config.md). Then you call `match()` on the `Hikaku` class.
The match result is sent to one or multiple `Reporter`. If the test fails kotlin's `DefaultAsserter.fail()` method is called.

### Example

There is an artifact for each converter. So we need one dependency for the specification and one for the implementation. In this example our project consists of an OpenAPI specification and a Spring implementation. The specification does not contain the _/error_ endpoints created by spring, so we want to omit those.
First add the dependencies for the converters, that we want to use. In this case `hikaku-openapi` and `hikaku-spring`.

```gradle
dependencies {
    testImplementation "de.codecentric.hikaku:hikaku-openapi:$hikakuVersion"
    testImplementation "de.codecentric.hikaku:hikaku-spring:$hikakuVersion"
}
```

#### Kotlin

And now we can create the test case:

```kotlin
@SpringBootTest
class SpecificationTest {

    @Autowired
    private lateinit var springContext: ApplicationContext

    @Test
    fun `specification matches implementation`() {
        Hikaku(
                specification = OpenApiConverter(Paths.get("openapi.yaml")),
                implementation = SpringConverter(springContext),
                config = HikakuConfig(
                        filters = listOf(SpringConverter.IGNORE_ERROR_ENDPOINT)
                )
        )
        .match()
    }
}
```

#### Java

Same example in Java:

```java
@SpringBootTest
public class SpecificationTest {

  @Autowired
  private ApplicationContext springContext;

  @Test
  public void specification_matches_implementation() {
    List<Function1<Endpoint, Boolean>> filters = new ArrayList<>();
    filters.add(SpringConverter.IGNORE_ERROR_ENDPOINT);

    List<Reporter> reporters = new ArrayList<>();
    reporters.add(new CommandLineReporter());

    new Hikaku(
            new OpenApiConverter(Paths.get("openapi.json")),
            new SpringConverter(springContext),
            new HikakuConfig(
                    reporters,
                    filters
            )
    )
    .match();
  }
}
```

## Limitations
Hikaku checks the implementation with static code analysis. So everything that is highly dynamic is not covered by hikaku. There might be other libraries and frameworks that can cover these aspects by checking the behavior.

### http status codes
For implementations the status codes are very dynamic. There are various ways to set a http status. For example using a `ResponseEntity` object in spring or using additional filters and so on. That's why hikaku does not support http status codes.

### Request and response object
For implementations both request and response objects are highly dynamic. For response objects there might be a generic `ResponseEntity` as well or interfaces with different implementations can be used. In both cases (request and response) the objects can be altered by a serialization library and there a lot of different libs out there. That's why hikaku neither supports request nor response objects.

## More Info

* **Blog (english):** [Spotting mismatches between your spec and your REST-API with hikaku](https://blog.codecentric.de/en/2019/03/spot-mismatches-between-your-spec-and-your-rest-api/)
* **Blog (german):** [ Abweichungen zwischen Spezifikation und REST-API mit hikaku erkennen](https://blog.codecentric.de/2019/03/abweichungen-zwischen-rest-api-spezifikation-erkennen/)
* **Sample project** [A complete sample project](https://github.com/cc-jhr/hikaku-sample)


================================================
FILE: build.gradle
================================================
buildscript {
    ext {
        kotlinVersion = '1.5.21'
        jvmVersion = '1.8'
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
    }
}

plugins {
    id 'com.github.ben-manes.versions' version '0.39.0'
}

subprojects {
    apply plugin: 'idea'
    apply plugin: 'maven'
    apply plugin: 'signing'
    apply plugin: 'kotlin'
    apply plugin: 'java-library'

    version = '3.2.1-SNAPSHOT'
    sourceCompatibility = jvmVersion
    targetCompatibility = jvmVersion

    compileKotlin {
        kotlinOptions {
            freeCompilerArgs = ['-Xjsr305=strict']
            jvmTarget = jvmVersion
        }
    }

    compileTestKotlin {
        kotlinOptions {
            freeCompilerArgs = ['-Xjsr305=strict']
            jvmTarget = jvmVersion
        }
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
        api "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
        api "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"

        testImplementation 'org.junit.platform:junit-platform-launcher:1.7.2'
        testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
        testImplementation "org.jetbrains.kotlin:kotlin-test-junit5:$kotlinVersion"
        testImplementation 'org.assertj:assertj-core:3.20.2'
    }

    test {
        useJUnitPlatform()
    }

    task javadocJar(type: Jar) {
        archiveClassifier = 'javadoc'
        from javadoc
    }

    task sourcesJar(type: Jar) {
        archiveClassifier = 'sources'
        from sourceSets.main.allSource
    }

    artifacts {
        archives javadocJar, sourcesJar
    }

    signing {
        sign configurations.archives
    }

    uploadArchives {
        repositories {
            mavenDeployer {
                beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

                repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
                    authentication(userName: findProperty('ossrhUsername'), password: findProperty('ossrhPassword'))
                }

                snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
                    authentication(userName: findProperty('ossrhUsername'), password: findProperty('ossrhPassword'))
                }

                pom.project {
                    packaging = 'jar'

                    url ='https://github.com/codecentric/hikaku'

                    scm {
                        connection = 'scm:git:git://github.com/codecentric/hikaku.git'
                        developerConnection = 'scm:git:ssh://git@github.com:codecentric/hikaku.git'
                        url = 'https://github.com/codecentric/hikaku'
                    }

                    licenses {
                        license {
                            name = 'Apache License, Version 2.0'
                            url = 'http://www.apache.org/licenses/LICENSE-2.0'
                        }
                    }

                    developers {
                        developer {
                            id = 'cc-jhr'
                            name = 'Jannes Heinrich'
                            email = '34243889+cc-jhr@users.noreply.github.com'
                        }
                        developer {
                            id = 'lmller'
                            name = 'Lovis Möller'
                            email = 'lovis.moeller@codecentric.de'
                        }
                    }
                }
            }
        }
    }
}


================================================
FILE: core/build.gradle
================================================
group = 'de.codecentric.hikaku'
archivesBaseName = 'hikaku-core'

uploadArchives {
  repositories {
    mavenDeployer {
      pom.project {
        name = 'hikaku-core'
        description = 'A library that tests if the implementation of a REST-API meets its specification. This module contains the core elements which can be used to create additional converters and reporters.'
      }
    }
  }
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/Hikaku.kt
================================================
package de.codecentric.hikaku

import de.codecentric.hikaku.SupportedFeatures.Feature
import de.codecentric.hikaku.converters.EndpointConverter
import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.reporters.MatchResult
import de.codecentric.hikaku.reporters.Reporter
import kotlin.test.fail

/**
 * Entry point for writing a hikaku test. Provide the [EndpointConverter]s and call [match] to test if the specification and the implementation of your REST-API match.
 * @param specification An [EndpointConverter] which converts your specification for the equality check.
 * @param implementation An [EndpointConverter]  which converts your implementation for the equality check.
 * @param config The configuration is optional. It lets you control the matching.
 */
class Hikaku(
        private val specification: EndpointConverter,
        private val implementation: EndpointConverter,
        var config: HikakuConfig = HikakuConfig()
) {
    private val supportedFeatures = SupportedFeatures(specification.supportedFeatures.intersect(implementation.supportedFeatures))

    private fun Set<Endpoint>.applyConfig(config: HikakuConfig): List<Endpoint> {
        val result = this.toMutableList()

        config.filters.forEach {
            result.removeAll(this.filter(it))
        }

        return result
    }

    private fun reportResult(matchResult: MatchResult) {
        config.reporters.forEach { it.report(matchResult) }
    }

    /**
     * Calling this method creates a [MatchResult]. It will be passed to the [Reporter] defined in the configuration and call [assert] with the end result.
     */
    fun match() {
        val specificationEndpoints = specification
                .conversionResult
                .applyConfig(config)
                .toSet()

        val implementationEndpoints = implementation
                .conversionResult
                .applyConfig(config)
                .toSet()

        val notExpected = implementationEndpoints.toMutableSet()
        val notFound = specificationEndpoints.toMutableSet()

        specificationEndpoints.forEach { currentEndpoint ->
            if (iterableContains(notExpected, currentEndpoint)) {
                notExpected.removeIf(endpointMatches(currentEndpoint))
                notFound.removeIf(endpointMatches(currentEndpoint))
            }
        }

        reportResult(
                MatchResult(
                        supportedFeatures,
                        specificationEndpoints,
                        implementationEndpoints,
                        notFound,
                        notExpected
                )
        )

        if (notExpected.isNotEmpty() || notFound.isNotEmpty()) {
            fail("Implementation does not match specification.")
        }
    }

    private fun endpointMatches(otherEndpoint: Endpoint): (Endpoint) -> Boolean {
        return {
            var matches = true
            matches = matches && it.path == otherEndpoint.path
            matches = matches && it.httpMethod == otherEndpoint.httpMethod

            supportedFeatures.forEach { feature ->
                matches = when (feature) {
                    Feature.QueryParameters -> matches && it.queryParameters == otherEndpoint.queryParameters
                    Feature.PathParameters -> matches && it.pathParameters ==  otherEndpoint.pathParameters
                    Feature.HeaderParameters -> matches && it.headerParameters == otherEndpoint.headerParameters
                    Feature.MatrixParameters -> matches && it.matrixParameters == otherEndpoint.matrixParameters
                    Feature.Produces -> matches && it.produces == otherEndpoint.produces
                    Feature.Consumes -> matches && it.consumes == otherEndpoint.consumes
                    Feature.Deprecation -> matches && it.deprecated == otherEndpoint.deprecated
                }
            }

            matches
        }
    }

    private fun iterableContains(notExpected: Set<Endpoint>, value: Endpoint) = notExpected.any(endpointMatches(value))
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/HikakuConfig.kt
================================================
package de.codecentric.hikaku

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.reporters.CommandLineReporter
import de.codecentric.hikaku.reporters.MatchResult
import de.codecentric.hikaku.reporters.Reporter

/**
 * Configuration for [Hikaku] class. It lets you partially control the matching process.
 * @param reporters The [MatchResult] will be passed to one or many [Reporter] before the test either fails or succeeds. Default is a [CommandLineReporter] that prints the results to [System.out].
 * @param filters Filtering rule: [Endpoint]s matching the predicate will be ignored.
 */
data class HikakuConfig
@JvmOverloads constructor(
        val reporters: List<Reporter> = listOf(CommandLineReporter()),
        val filters: List<(Endpoint) -> Boolean> = emptyList()
)

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/SupportedFeatures.kt
================================================
package de.codecentric.hikaku

import de.codecentric.hikaku.converters.EndpointConverter

/**
 * A list of features supported by an [EndpointConverter].
 */
class SupportedFeatures(
    private val supportedFeatures: Set<Feature> = emptySet()
) : Set<SupportedFeatures.Feature> by supportedFeatures {

    constructor(vararg feature: Feature): this(feature.toSet())

    enum class Feature {
        /** Checks the equality of query parameters. */
        QueryParameters,
        /** Checks the equality of path parameters. */
        PathParameters,
        /** Checks the equality of header parameters. */
        HeaderParameters,
        /** Checks supported media type of responses. */
        Produces,
        /** Checks supported media type of requests. */
        Consumes,
        /** Checks the equality of matrix parameters. */
        MatrixParameters,
        /** Checks the equality of deprecation. */
        Deprecation
    }
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/converters/AbstractEndpointConverter.kt
================================================
package de.codecentric.hikaku.converters

import de.codecentric.hikaku.endpoints.Endpoint

/**
 * Abstract [EndpointConverter] which triggers conversion when accessing the [conversionResult]s.
 */
abstract class AbstractEndpointConverter : EndpointConverter {

    override val conversionResult: Set<Endpoint> by lazy {
        this.convert()
    }

    abstract fun convert(): Set<Endpoint>
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/converters/ClassLocator.kt
================================================
package de.codecentric.hikaku.converters

import de.codecentric.hikaku.extensions.extension
import de.codecentric.hikaku.extensions.nameWithoutExtension
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths

/**
 * Original code snippet found at [dzone](https://dzone.com/articles/get-all-classes-within-package) posted by [Victor Tatai](https://dzone.com/users/74061/vtatai.html).
 */
object ClassLocator {

    fun getClasses(packageName: String): List<Class<*>> {
        val classLoader = Thread.currentThread().contextClassLoader
        val path = packageName.replace('.', '/')
        val resources = classLoader.getResources(path)
        val dirs = mutableListOf<Path>()

        resources.iterator().forEach {
            dirs.add(Paths.get(it.toURI()))
        }

        val classes = mutableListOf<Class<*>>()

        for (directory in dirs) {
            classes.addAll(findClasses(directory, packageName))
        }

        return classes
    }

    private fun findClasses(directory: Path, packageName: String): List<Class<*>> {
        val classes = mutableListOf<Class<*>>()

        if (!Files.exists(directory)) {
            return classes
        }

        Files.list(directory)
                .forEach {
                    if (Files.isDirectory(it)) {
                        classes.addAll(findClasses(it, "$packageName.${it.fileName}"))
                    } else if (it.extension() == "class") {
                        classes.add(Class.forName("$packageName.${it.nameWithoutExtension()}"))
                    }
                }

        return classes
    }
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/converters/EndpointConverter.kt
================================================
package de.codecentric.hikaku.converters

import de.codecentric.hikaku.SupportedFeatures
import de.codecentric.hikaku.SupportedFeatures.Feature
import de.codecentric.hikaku.endpoints.Endpoint

/**
 * Converts either a specific type of specification or implementation into the internal hikaku format in order to be able to perform a matching on the extracted components.
 */
interface EndpointConverter {

    /** Result of the conversion containing all extracted [Endpoint]s. */
    val conversionResult: Set<Endpoint>

    /** List of [Feature]s that this [EndpointConverter]s supports. */
    val supportedFeatures: SupportedFeatures
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/converters/EndpointConverterException.kt
================================================
package de.codecentric.hikaku.converters

/**
 * Is thrown in case an [EndpointConverter] is not able to perform the conversion.
 */
class EndpointConverterException(message: String? = null, cause: Throwable? = null) : Throwable(message, cause) {
    constructor(throwable: Throwable): this(throwable.message, throwable)
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/endpoints/Endpoint.kt
================================================
package de.codecentric.hikaku.endpoints

/**
 * A single [Endpoint] containing all information. Each [Endpoint] consists of exactly one path in combination with exactly one [HttpMethod].
 * If a REST endpoint supports multiple [HttpMethod]s, this will result in multiple [Endpoint] instances.
 * @param path The path excluding a base path. **Example:** `/todos`
 * @param produces Supported media types for the response.
 * @param consumes Supported media types for the request.
 */
data class Endpoint(
        val path: String,
        val httpMethod: HttpMethod,
        val queryParameters: Set<QueryParameter> = emptySet(),
        val pathParameters: Set<PathParameter> = emptySet(),
        val headerParameters: Set<HeaderParameter> = emptySet(),
        val matrixParameters: Set<MatrixParameter> = emptySet(),
        val produces: Set<String> = emptySet(),
        val consumes: Set<String> = emptySet(),
        val deprecated: Boolean = false
)

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/endpoints/HeaderParameter.kt
================================================
package de.codecentric.hikaku.endpoints

data class HeaderParameter(
    val parameterName: String,
    val required: Boolean = false
)

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/endpoints/HttpMethod.kt
================================================
package de.codecentric.hikaku.endpoints

enum class HttpMethod {
    GET,
    POST,
    HEAD,
    PUT,
    PATCH,
    DELETE,
    TRACE,
    OPTIONS
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/endpoints/MatrixParameter.kt
================================================
package de.codecentric.hikaku.endpoints

data class MatrixParameter(
        val parameterName: String,
        val required: Boolean = false
)

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/endpoints/PathParameter.kt
================================================
package de.codecentric.hikaku.endpoints

data class PathParameter(
        val parameterName: String
)

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/endpoints/QueryParameter.kt
================================================
package de.codecentric.hikaku.endpoints

data class QueryParameter(
        val parameterName: String,
        val required: Boolean = false
)

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/extensions/ClassExtensions.kt
================================================
package de.codecentric.hikaku.extensions

import kotlin.reflect.KClass
import kotlin.reflect.jvm.jvmName

fun KClass<*>.isUnit(): Boolean {
    return this.isInstance(Unit) ||
    this.jvmName == "java.lang.Void" ||
    this.jvmName == "void"
}

fun KClass<*>.isString(): Boolean {
    return this.isInstance(String) ||
            this.jvmName == "java.lang.String"
}


================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/extensions/FileExtensions.kt
================================================
package de.codecentric.hikaku.extensions

import java.io.File

fun File.checkFileValidity(vararg extensions: String) {
    this.toPath().checkFileValidity(*extensions)
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/extensions/PathExtensions.kt
================================================
package de.codecentric.hikaku.extensions

import java.nio.file.Files
import java.nio.file.Path

fun Path.nameWithoutExtension() = fileName.toString().substringBeforeLast(".")

fun Path.extension() = fileName.toString().substringAfterLast(".")

fun Path.checkFileValidity(vararg extensions: String) {
    require(Files.exists(this)) { "Given file does not exist." }
    require(Files.isRegularFile(this)) { "Given file is not a regular file." }

    if (extensions.isNotEmpty()) {
        extensions.map {it.substringAfter('.') }
                .filter { this.extension() == it }
                .ifEmpty { throw IllegalArgumentException("Given file is not of type ${extensions.joinToString()}") }
    }
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/reporters/CommandLineReporter.kt
================================================
package de.codecentric.hikaku.reporters

import de.codecentric.hikaku.SupportedFeatures
import de.codecentric.hikaku.SupportedFeatures.*
import de.codecentric.hikaku.endpoints.*

/**
 * Simply prints the result to [System.out].
 */
class CommandLineReporter : Reporter {

    override fun report(endpointMatchResult: MatchResult) {
        val heading = "hikaku test result:"

        println("\n")
        println(heading)
        println("#".repeat(heading.length))

        val features = endpointMatchResult.supportedFeatures.joinToString(separator = ", ")
        println("The following features were used for matching: HttpMethod, Path, $features")


        if (endpointMatchResult.notFound.isEmpty() && endpointMatchResult.notExpected.isEmpty()) {
            println ("")
            println ("✅ Test successful. Specification and implementation match.")
        }


        if (endpointMatchResult.notFound.isNotEmpty()) {
            println("\n👀 Expected, but unable to find:")

            endpointMatchResult.notFound.forEach {
                printEndpoint(endpointMatchResult.supportedFeatures, it)
            }
        }

        if (endpointMatchResult.notExpected.isNotEmpty()) {
            println("\n👻 Unexpected, but found:")

            endpointMatchResult.notExpected.forEach {
                printEndpoint(endpointMatchResult.supportedFeatures, it)
            }
        }
    }

    private fun printEndpoint(supportedFeatures: SupportedFeatures, endpoint: Endpoint) {
        var path = "< ${endpoint.httpMethod} ${endpoint.path}"

        supportedFeatures.forEach {
            path += when(it) {
                Feature.QueryParameters -> listQueryParameters(endpoint.queryParameters)
                Feature.PathParameters -> listPathParameters(endpoint.pathParameters)
                Feature.HeaderParameters -> listHeaderParameter(endpoint.headerParameters)
                Feature.MatrixParameters -> listMatrixParameter(endpoint.matrixParameters)
                Feature.Consumes -> listRequestMediaTypes(endpoint.consumes)
                Feature.Produces -> listResponseMediaTypes(endpoint.produces)
                Feature.Deprecation -> if (endpoint.deprecated) "  Deprecated" else ""
            }
        }

        println("$path >")
    }

    private fun listQueryParameters(queryParameters: Set<QueryParameter>) =
            "  QueryParameters[${queryParameters.joinToString {
                "${it.parameterName} (${if(it.required) "required" else "optional"})"
            }}]"

    private fun listPathParameters(pathParameters: Set<PathParameter>) =
            "  PathParameters[${pathParameters.joinToString {
                it.parameterName
            }}]"

    private fun listHeaderParameter(headerParameters: Set<HeaderParameter>) =
            "  HeaderParameters[${headerParameters.joinToString {
                "${it.parameterName} (${if(it.required) "required" else "optional"})"
            }}]"

    private fun listMatrixParameter(matrixParameters: Set<MatrixParameter>) =
            "  MatrixParameters[${matrixParameters.joinToString {
                "${it.parameterName} (${if(it.required) "required" else "optional"})"
            }}]"

    private fun listRequestMediaTypes(requestMediaTypes: Set<String>) =
            "  Consumes[${requestMediaTypes.joinToString()}]"

    private fun listResponseMediaTypes(responseMediaTypes: Set<String>) =
            "  Produces[${responseMediaTypes.joinToString()}]"
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/reporters/MatchResult.kt
================================================
package de.codecentric.hikaku.reporters

import de.codecentric.hikaku.SupportedFeatures
import de.codecentric.hikaku.endpoints.Endpoint

/**
 * Contains the complete result.
 * @param supportedFeatures Contains all features which have been used for the match.
 * @param specificationEndpoints All [Endpoint]s extracted from the specification.
 * @param implementationEndpoints All [Endpoint]s extracted from the implementation.
 * @param notFound A [Set] of [Endpoint]s which were expected due to their existence in the specification, but which couldn't be found.
 * @param notExpected A [Set] of [Endpoint]s which have been found in the implementation, but which were unexpected, because they don't exist in the specification.
 */
data class MatchResult(
        val supportedFeatures: SupportedFeatures,
        val specificationEndpoints: Set<Endpoint>,
        val implementationEndpoints: Set<Endpoint>,
        val notFound: Set<Endpoint>,
        val notExpected: Set<Endpoint>
)

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/reporters/NoOperationReporter.kt
================================================
package de.codecentric.hikaku.reporters

/**
 * Receives the result and does nothing.
 */
class NoOperationReporter : Reporter {
    override fun report(endpointMatchResult: MatchResult) { }
}

================================================
FILE: core/src/main/kotlin/de/codecentric/hikaku/reporters/Reporter.kt
================================================
package de.codecentric.hikaku.reporters

/**
 * A [Reporter] will receive the [MatchResult] before the test terminates.
 */
interface Reporter {
    fun report(endpointMatchResult: MatchResult)
}

================================================
FILE: core/src/main/resources/.gitemptydir
================================================


================================================
FILE: core/src/test/kotlin/de/codecentric/hikaku/HikakuTest.kt
================================================
package de.codecentric.hikaku

import de.codecentric.hikaku.SupportedFeatures.Feature
import de.codecentric.hikaku.converters.EndpointConverter
import de.codecentric.hikaku.endpoints.*
import de.codecentric.hikaku.endpoints.HttpMethod.*
import de.codecentric.hikaku.reporters.MatchResult
import de.codecentric.hikaku.reporters.NoOperationReporter
import de.codecentric.hikaku.reporters.Reporter
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.opentest4j.AssertionFailedError
import kotlin.test.assertFailsWith

class HikakuTest {

    @Nested
    inner class EndpointBasicsTests {

        @Test
        fun `specification and implementation having different amounts of endpoints in conversion results let the test fail`() {
            //given
            val specificationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val implementationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET),
                        Endpoint("/todos", HEAD)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val hikaku = Hikaku(
                    specificationDummyConverter,
                    implementationDummyConverter,
                    HikakuConfig(
                            reporters = listOf(NoOperationReporter())
                    )
            )

            //when
            assertFailsWith<AssertionError> {
                hikaku.match()
            }
        }

        @Test
        fun `paths in random order match`() {
            //given
            val specificationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/c", GET),
                        Endpoint("/a", GET),
                        Endpoint("/b", GET)

                )
                override val supportedFeatures = SupportedFeatures()
            }

            val implementationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/b", GET),
                        Endpoint("/c", GET),
                        Endpoint("/a", GET)
                )
                override val supportedFeatures = SupportedFeatures(Feature.PathParameters)
            }

            val hikaku = Hikaku(
                    specificationDummyConverter,
                    implementationDummyConverter,
                    HikakuConfig(
                            reporters = listOf(NoOperationReporter())
                    )
            )

            //when
            hikaku.match()
        }

        @Test
        fun `same number of Endpoints, but paths don't match`() {
            //given
            val specificationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/c", GET),
                        Endpoint("/a", GET),
                        Endpoint("/b", GET)

                )
                override val supportedFeatures = SupportedFeatures()
            }

            val implementationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/y", GET),
                        Endpoint("/z", GET),
                        Endpoint("/a", GET)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val hikaku = Hikaku(
                    specificationDummyConverter,
                    implementationDummyConverter,
                    HikakuConfig(
                            reporters = listOf(NoOperationReporter())
                    )
            )

            //when
            assertFailsWith<AssertionFailedError> {
                hikaku.match()
            }
        }

        @Test
        fun `http methods in random order match`() {
            //given
            val specificationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", POST),
                        Endpoint("/todos", DELETE),
                        Endpoint("/todos", GET)

                )
                override val supportedFeatures = SupportedFeatures()
            }

            val implementationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET),
                        Endpoint("/todos", POST),
                        Endpoint("/todos", DELETE)
                )
                override val supportedFeatures = SupportedFeatures(Feature.PathParameters)
            }

            val hikaku = Hikaku(
                    specificationDummyConverter,
                    implementationDummyConverter,
                    HikakuConfig(
                            reporters = listOf(NoOperationReporter())
                    )
            )

            //when
            hikaku.match()
        }

        @Test
        fun `same number of Endpoints, but http methods don't match`() {
            //given
            val specificationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", PUT),
                        Endpoint("/todos", DELETE),
                        Endpoint("/todos", GET)

                )
                override val supportedFeatures = SupportedFeatures()
            }

            val implementationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET),
                        Endpoint("/todos", POST),
                        Endpoint("/todos", HEAD)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val hikaku = Hikaku(
                    specificationDummyConverter,
                    implementationDummyConverter,
                    HikakuConfig(
                            reporters = listOf(NoOperationReporter())
                    )
            )

            //when
            assertFailsWith<AssertionFailedError> {
                hikaku.match()
            }
        }
    }

    @Nested
    inner class FeatureTests {

        @Nested
        inner class PathParameterTests {

            @Test
            fun `path parameter in random order match if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos/{organizationId}/{accountId}",
                                    httpMethod = GET,
                                    pathParameters = setOf(
                                            PathParameter("accountId"),
                                            PathParameter("organizationId")
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos/{organizationId}/{accountId}",
                                    httpMethod = GET,
                                    pathParameters = setOf(
                                            PathParameter("organizationId"),
                                            PathParameter("accountId")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `path parameter are skipped if the feature is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos/{id}",
                                    httpMethod = GET,
                                    pathParameters = setOf(
                                            PathParameter("id")
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos/{id}",
                                    httpMethod = GET,
                                    pathParameters = setOf(
                                            PathParameter("othername")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `path parameter don't match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos/{accountId}",
                                    httpMethod = GET,
                                    pathParameters = setOf(
                                            PathParameter("accountId")
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos/{id}",
                                    httpMethod = GET,
                                    pathParameters = setOf(
                                            PathParameter("id")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.PathParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }
        }

        @Nested
        inner class QueryParameterNameTests {

            @Test
            fun `query parameter names in random order match if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("filter"),
                                            QueryParameter("tag"),
                                            QueryParameter("query")
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("query"),
                                            QueryParameter("filter"),
                                            QueryParameter("tag")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `query parameter names are skipped if the feature is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("filter")
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("tag")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `query parameter names don't match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("filter")
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("tag")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }

            @Test
            fun `query parameter required matches if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("filter", true)
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("filter", true)
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `query parameter required is skipped if option is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("filter", true)
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("filter", false)
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `query parameter required don't match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("filter", true)
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    queryParameters = setOf(
                                            QueryParameter("filter", false)
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.QueryParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }
        }

        @Nested
        inner class HeaderParameterNameTests {

            @Test
            fun `header parameter names in random order match if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("x-b3-traceid"),
                                            HeaderParameter("allow-cache")
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("allow-cache"),
                                            HeaderParameter("x-b3-traceid")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `header parameter names are skipped if the feature is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("allow-cache")
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("x-b3-traceid")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `header parameter names don't match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("cache")
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("allow-cache")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }

            @Test
            fun `header parameter required matches if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("allow-cache", true)
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("allow-cache", true)
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `header parameter required is skipped if option is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("allow-cache", false)
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("allow-cache", true)
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `header parameter required don't match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("allow-cache", true)
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("allow-cache", false)
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.HeaderParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }
        }

        @Nested
        inner class MatrixParameterNameTests {

            @Test
            fun `matrix parameter names in random order match if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("tag"),
                                            MatrixParameter("done")
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("done"),
                                            MatrixParameter("tag")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `matrix parameter names are skipped if the feature is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("done")
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("tag")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `matrix parameter names don't match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("tag")
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("done")
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }

            @Test
            fun `matrix parameter required matches if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("tag", true)
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("tag", true)
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `matrix parameter required is skipped if option is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("tag", true)
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    headerParameters = setOf(
                                            HeaderParameter("tag", false)
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `matrix parameter required don't match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("allow-cache", true)
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    matrixParameters = setOf(
                                            MatrixParameter("allow-cache", false)
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.MatrixParameters)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }
        }

        @Nested
        inner class ProducesTests {

            @Test
            fun `media types in random order match if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    produces = setOf(
                                            "application/json",
                                            "text/plain"
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Produces)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    produces = setOf(
                                            "text/plain",
                                            "application/json"
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Produces)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `produces is skipped if the feature is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    produces = setOf(
                                            "application/xml",
                                            "text/plain"
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    produces = setOf(
                                            "application/json"
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Produces)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `media types don't match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    produces = setOf(
                                            "application/xml",
                                            "text/plain"
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Produces)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    produces = setOf(
                                            "application/json"
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Produces)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }
        }

        @Nested
        inner class ConsumesTests {

            @Test
            fun `media types in random order match if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    consumes = setOf(
                                            "application/json",
                                            "text/plain"
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    consumes = setOf(
                                            "text/plain",
                                            "application/json"
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `produces is skipped if the feature is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    consumes = setOf(
                                            "application/xml",
                                            "text/plain"
                                    )
                            )

                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    consumes = setOf(
                                            "application/json"
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `media types don't match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    consumes = setOf(
                                            "application/xml",
                                            "text/plain"
                                    )
                            )

                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    consumes = setOf(
                                            "application/json"
                                    )
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Consumes)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }
        }

        @Nested
        inner class DeprecationTests {

            @Test
            fun `deprecation info in random order match if the feature is supported by both converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    deprecated = false
                            ),
                            Endpoint(
                                    path = "/todos/tags",
                                    httpMethod = GET,
                                    deprecated = true
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos/tags",
                                    httpMethod = GET,
                                    deprecated = true
                            ),
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    deprecated = false
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `deprecation info is skipped if the feature is not supported by one of the converters`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    deprecated = false
                            )
                    )

                    override val supportedFeatures = SupportedFeatures()
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    deprecated = true
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                hikaku.match()
            }

            @Test
            fun `deprecation info does not match`() {
                //given
                val specificationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    deprecated = false
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)
                }

                val implementationDummyConverter = object : EndpointConverter {
                    override val conversionResult: Set<Endpoint> = setOf(
                            Endpoint(
                                    path = "/todos",
                                    httpMethod = GET,
                                    deprecated = true
                            )
                    )
                    override val supportedFeatures = SupportedFeatures(Feature.Deprecation)
                }

                val hikaku = Hikaku(
                        specificationDummyConverter,
                        implementationDummyConverter,
                        HikakuConfig(
                                reporters = listOf(NoOperationReporter())
                        )
                )

                //when
                assertFailsWith<AssertionFailedError> {
                    hikaku.match()
                }
            }
        }
    }

    @Nested
    inner class ConfigTests {

        @Test
        fun `ignore endpoints with http method HEAD and OPTIONS on specification`() {
            //given
            val dummyConverterWithHeadAndOptions = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET),
                        Endpoint("/todos", HEAD),
                        Endpoint("/todos", OPTIONS)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val dummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val hikaku = Hikaku(
                    dummyConverterWithHeadAndOptions,
                    dummyConverter,
                    HikakuConfig(
                            filters = listOf (
                                { endpoint -> endpoint.httpMethod == HEAD },
                                { endpoint -> endpoint.httpMethod == OPTIONS }
                            ),
                            reporters = listOf(NoOperationReporter())
                    )
            )

            //when
            hikaku.match()
        }

        @Test
        fun `ignore endpoints with http method HEAD and OPTIONS on implementation`() {
            //given
            val dummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val dummyConverterWithHeadAndOptions = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET),
                        Endpoint("/todos", HEAD),
                        Endpoint("/todos", OPTIONS)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val hikaku = Hikaku(
                    dummyConverter,
                    dummyConverterWithHeadAndOptions,
                    HikakuConfig(
                            filters = listOf (
                                    { endpoint -> endpoint.httpMethod == HEAD },
                                    { endpoint -> endpoint.httpMethod == OPTIONS }
                            ),
                            reporters = listOf(NoOperationReporter())
                    )
            )

            //when
            hikaku.match()
        }

        @Test
        fun `ignore specific paths`() {
            //given
            val specificationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val implementationDummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET),
                        Endpoint("/error", GET),
                        Endpoint("/error", HEAD),
                        Endpoint("/error", OPTIONS),
                        Endpoint("/actuator/health", OPTIONS)
                )
                override val supportedFeatures = SupportedFeatures()
            }

            val hikaku = Hikaku(
                    specificationDummyConverter,
                    implementationDummyConverter,
                    HikakuConfig(
                            filters = listOf (
                                    { endpoint -> endpoint.path == "/error" },
                                    { endpoint -> endpoint.path.startsWith("/actuator") }
                            ),
                            reporters = listOf(NoOperationReporter())
                    )
            )

            //when
            hikaku.match()
        }
    }

    @Nested
    inner class ReporterTests {

        @Test
        fun `MatchResult has to be passed to the Reporter`() {
            //given
            val dummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET)
                )
                override val supportedFeatures = SupportedFeatures()
            }


            val reporter = object : Reporter {
                var hasBeenCalled: Boolean = false

                override fun report(endpointMatchResult: MatchResult) {
                    hasBeenCalled = true
                }
            }

            val hikaku = Hikaku(
                    dummyConverter,
                    dummyConverter,
                    HikakuConfig(
                            reporters = listOf(reporter)
                    )
            )

            //when
            hikaku.match()

            //then
            assertThat(reporter.hasBeenCalled).isTrue()
        }

        @Test
        fun `MatchResult can be passed to multiple Reporter`() {
            //given
            val dummyConverter = object : EndpointConverter {
                override val conversionResult: Set<Endpoint> = setOf(
                        Endpoint("/todos", GET)
                )
                override val supportedFeatures = SupportedFeatures()
            }


            val firstReporter = object : Reporter {
                var hasBeenCalled: Boolean = false

                override fun report(endpointMatchResult: MatchResult) {
                    hasBeenCalled = true
                }
            }

            val secondReporter = object : Reporter {
                var hasBeenCalled: Boolean = false

                override fun report(endpointMatchResult: MatchResult) {
                    hasBeenCalled = true
                }
            }

            val hikaku = Hikaku(
                    dummyConverter,
                    dummyConverter,
                    HikakuConfig(
                            reporters = listOf(firstReporter, secondReporter)
                    )
            )

            //when
            hikaku.match()

            //then
            assertThat(firstReporter.hasBeenCalled).isTrue()
            assertThat(secondReporter.hasBeenCalled).isTrue()
        }
    }
}

================================================
FILE: core/src/test/kotlin/de/codecentric/hikaku/extensions/ClassExtensionsTest.kt
================================================
package de.codecentric.hikaku.extensions

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import java.lang.String as JavaString

class ClassExtensionsTest {

    @Nested
    inner class IsUnitTests {

        @Test
        fun `returns true for kotlin type Unit`() {
            // given
            val obj = Unit::class

            // when
            val result = obj.isUnit()

            // then
            assertThat(result).isTrue()
        }

        @Test
        fun `returns true for java type Void`() {
            // given
            val obj = Void::class

            // when
            val result = obj.isUnit()

            // then
            assertThat(result).isTrue()
        }

        @Test
        fun `returns false for any other type`() {
            // given
            val obj = Int::class

            // when
            val result = obj.isUnit()

            // then
            assertThat(result).isFalse()
        }
    }

    @Nested
    inner class IsStringTests {

        @Test
        fun `returns true for kotlin type String`() {
            // given
            val obj = String::class

            // when
            val result = obj.isString()

            // then
            assertThat(result).isTrue()
        }

        @Test
        fun `returns true for java type String`() {
            // given
            val obj = JavaString::class

            // when
            val result = obj.isString()

            // then
            assertThat(result).isTrue()
        }

        @Test
        fun `returns false for any other type`() {
            // given
            val obj = Int::class

            // when
            val result = obj.isString()

            // then
            assertThat(result).isFalse()
        }
    }
}


================================================
FILE: core/src/test/kotlin/de/codecentric/hikaku/extensions/FileExtensionsTest.kt
================================================
package de.codecentric.hikaku.extensions

import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import java.io.File
import kotlin.io.path.createTempDirectory
import kotlin.test.assertFailsWith

class FileExtensionsTest {

    @Nested
    inner class CheckValidityTests {

        @Test
        fun `non-existing file throws an exception`() {
            assertFailsWith<IllegalArgumentException> {
                File("test-file-which-does-not-exist.spec").checkFileValidity()
            }
        }

        @Test
        fun `directory in validity check throws an exception`() {
            assertFailsWith<IllegalArgumentException> {
                createTempDirectory().checkFileValidity()
            }
        }

        @Test
        fun `existing file with invalid file extension throws an exception`() {
            assertFailsWith<IllegalArgumentException> {
                File(this::class.java.classLoader.getResource("test_file.txt").toURI()).checkFileValidity(".css")
            }
        }

        @Test
        fun `file is valid without extension check`() {
            //given
            val file = File(this::class.java.classLoader.getResource("test_file.txt").toURI())

            //when
            file.checkFileValidity()

            //then
            //no exception is thrown
        }

        @Test
        fun `file is valid with extension check`() {
            //given
            val file = File(this::class.java.classLoader.getResource("test_file.txt").toURI())

            //when
            file.checkFileValidity(".txt")

            //then
            //no exception is thrown
        }
    }
}

================================================
FILE: core/src/test/kotlin/de/codecentric/hikaku/extensions/PathExtensionsTest.kt
================================================
package de.codecentric.hikaku.extensions

import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import java.nio.file.Files.createTempDirectory
import java.nio.file.Paths
import kotlin.test.assertFailsWith

class PathExtensionsTest {

    @Nested
    inner class CheckValidityTests {

        @Test
        fun `non-existing file throws an exception`() {
            assertFailsWith<IllegalArgumentException> {
                Paths.get("test-file-which-does-not-exist.spec").checkFileValidity()
            }
        }

        @Test
        fun `directory in validity check throws an exception`() {
            assertFailsWith<IllegalArgumentException> {
                createTempDirectory("tmp").checkFileValidity()
            }
        }

        @Test
        fun `existing file with invalid file extension throws an exception`() {
            assertFailsWith<IllegalArgumentException> {
                Paths.get(this::class.java.classLoader.getResource("test_file.txt").toURI()).checkFileValidity(".css")
            }
        }

        @Test
        fun `file is valid without extension check`() {
            //given
            val file = Paths.get(this::class.java.classLoader.getResource("test_file.txt").toURI())

            //when
            file.checkFileValidity()

            //then
            //no exception is thrown
        }

        @Test
        fun `file is valid with extension check`() {
            //given
            val file = Paths.get(this::class.java.classLoader.getResource("test_file.txt").toURI())

            //when
            file.checkFileValidity(".txt")

            //then
            //no exception is thrown
        }
    }
}

================================================
FILE: core/src/test/resources/test_file.txt
================================================


================================================
FILE: docs/config.md
================================================
# hikaku - Config

The following is a list if configurations.

| config parameter | since | default value | description |
| --- | --- | --- | --- |
| filters | 3.0.0 | `emptyList()` | Endpoints matching the predicates in this list will be excluded from matching. |
| reporters | 1.0.0 | `CommandLineReporter()` | A reporter receives the match results before the assertion is called. Default value is the `CommandLineReporter` which simply prints the results to command line. Another built-in option is the `NoOperationReporter` which does nothing. |

================================================
FILE: docs/features.md
================================================
# hikaku - Features

The following table gives an overview of all features and which converter supports which feature.
The check for endpoint paths and http methods are base functions that every converter has to support. Those are not listed in the table below.
There might be various ways to declare or use a feature, so check each converter for unsupported features as well. 

| Feature Name | Description | [OpenApi Converter](../openapi/README.md)| [Spring Converter](../spring/README.md) | [WADL Converter](../wadl/README.md) | [RAML Converter](../raml/README.md) | [JAX-RS Converter](../jax-rs/README.md) | [Micronaut Converter](../micronaut/README.md) |
| --- | --- | --- | --- | --- | --- | --- | --- |
| QueryParameters | Name of a query parameter and whether the parameter is required or not. _Example:_ `/todos?filter=all`| ✅ _(1.0.0)_ | ✅ _(1.0.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |
| PathParameters | Name of a path parameter. _Example:_ `/todos/{id}`| ✅ _(1.0.0)_ | ✅ _(1.0.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |
| HeaderParameters | Name of a header parameter and whether the parameter is required or not. | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |
| MatrixParameters | Name of a matrix parameter and whether the parameter is required or not. _Example:_ `/todos;param=value` | ❌ | ✅ _(2.1.0)_ | ✅ _(2.1.0)_ | ❌ | ✅ _(2.1.0)_ | ❌ |
| Produces | Checks the supported media types of the response. | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |
| Consumes | Checks the supported media types of the request. | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(1.1.0)_ | ✅ _(2.0.0)_ | ✅ _(2.1.0)_ | ✅ _(2.3.0)_ |
| Deprecation | Checks deprecated endpoints are properly marked. | ✅ _(2.3.0)_ | ✅ _(2.3.0)_ | ❌ | ✅ _(2.3.0)_ | ✅ _(2.3.0)_ | ✅ _(2.3.0)_ |

================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists


================================================
FILE: gradlew
================================================
#!/usr/bin/env sh

#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
    echo "$*"
}

die () {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
  NONSTOP* )
    nonstop=true
    ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar


# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=`expr $i + 1`
    done
    case $i in
        0) set -- ;;
        1) set -- "$args0" ;;
        2) set -- "$args0" "$args1" ;;
        3) set -- "$args0" "$args1" "$args2" ;;
        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Escape application args
save () {
    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
    echo " "
}
APP_ARGS=`save "$@"`

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

exec "$JAVACMD" "$@"


================================================
FILE: gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem      https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem

@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar


@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: install-jdk.sh
================================================
#!/bin/bash
install_jdk () {
    if $jabba use $JDK; then
        echo $JDK was available and Jabba is using it
    else
        echo installing $JDK
        $jabba install "$JDK" || exit $?
        echo setting $JDK as Jabba default
        $jabba use $JDK || exit $?
    fi
}

unix_pre () {
    curl -sL https://github.com/shyiko/jabba/raw/master/install.sh | bash && . ~/.jabba/jabba.sh
    unset _JAVA_OPTIONS
    export jabba=jabba
}

linux () {
    unix_pre
}

osx () {
    unix_pre
    export JAVA_HOME="$HOME/.jabba/jdk/$JDK/Contents/Home"
}

windows () {
    PowerShell -ExecutionPolicy Bypass -Command '[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-Expression (Invoke-WebRequest https://github.com/shyiko/jabba/raw/master/install.ps1 -UseBasicParsing).Content'
    export jabba="$HOME/.jabba/bin/jabba.exe"
    # Windows is unable to clean child processes, so no Gradle daemon allowed
    export GRADLE_OPTS="-Dorg.gradle.daemon=false $GRADLE_OPTS"
    echo 'export GRADLE_OPTS="-Dorg.gradle.daemon=false $GRADLE_OPTS"' >> ~/.jdk_config
    # Apparently exported variables are ignored in subseguent phases on Windows. Write in config file
    echo "export JAVA_HOME=\"${JAVA_HOME}\"" >> ~/.jdk_config
    echo "export PATH=\"${PATH}\"" >> ~/.jdk_config
}

echo "running ${TRAVIS_OS_NAME}-specific configuration"
export JAVA_HOME="$HOME/.jabba/jdk/$JDK"
$TRAVIS_OS_NAME
export PATH="$JAVA_HOME/bin:$PATH"
install_jdk
which java
java -version

================================================
FILE: jax-rs/README.md
================================================
# hikaku - JAX-RS

Converter for JAX-RS. This converter can be used with frameworks that make use of JAX-RS. For instance:
+ [Apache CXF](http://cxf.apache.org)
+ [Dropwizard](https://www.dropwizard.io)
+ [Jersey](https://jersey.github.io)
+ [Resteasy](https://resteasy.github.io)
+ [Restlet](https://restlet.com/open-source/documentation/user-guide/2.3/extensions/jaxrs)
+ [Quarkus](https://quarkus.io)

## Feature Support

Please refer to the list of [all features](../docs/features.md). To check the feature support for this converter.

## Currently not supported

* Parameters defined on fields or setters

## Usage

Instantiate the converter with a package name which will be scanned recursively for controllers.

_Example_: `JaxRsConverter("de.codecentric.hikaku")`

================================================
FILE: jax-rs/build.gradle
================================================
group = 'de.codecentric.hikaku'
archivesBaseName = 'hikaku-jax-rs'

dependencies {
  api project(':core')
  api 'jakarta.ws.rs:jakarta.ws.rs-api:3.0.0'
}

uploadArchives {
  repositories {
    mavenDeployer {
      pom.project {
        name = 'hikaku-jax-rs'
        description = 'A library that tests if the implementation of a REST-API meets its specification. This module contains a converter for jax-rs implementations.'
      }
    }
  }
}


================================================
FILE: jax-rs/src/main/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverter.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.SupportedFeatures
import de.codecentric.hikaku.SupportedFeatures.Feature
import de.codecentric.hikaku.converters.AbstractEndpointConverter
import de.codecentric.hikaku.converters.ClassLocator
import de.codecentric.hikaku.converters.EndpointConverterException
import de.codecentric.hikaku.endpoints.*
import de.codecentric.hikaku.endpoints.HttpMethod
import de.codecentric.hikaku.extensions.isUnit
import jakarta.ws.rs.*
import java.lang.reflect.Method

class JaxRsConverter(private val packageName: String) : AbstractEndpointConverter() {

    override val supportedFeatures = SupportedFeatures(
            Feature.QueryParameters,
            Feature.PathParameters,
            Feature.HeaderParameters,
            Feature.MatrixParameters,
            Feature.Consumes,
            Feature.Produces,
            Feature.Deprecation
    )

    override fun convert(): Set<Endpoint> {
        if (packageName.isBlank()) {
            throw EndpointConverterException("Package name must not be blank.")
        }

        return ClassLocator.getClasses(packageName)
                .filter { it.getAnnotation(Path::class.java) != null }
                .flatMap { extractEndpoints(it) }
                .toSet()
    }

    private fun extractEndpoints(resource: Class<*>): List<Endpoint> {
        return resource.methods
                .filter { isHttpMethodAnnotationPresent(it) }
                .map { createEndpoint(resource, it) }
    }

    private fun isHttpMethodAnnotationPresent(method: Method): Boolean {
        return when {
            method.isAnnotationPresent(DELETE::class.java) -> true
            method.isAnnotationPresent(GET::class.java) -> true
            method.isAnnotationPresent(HEAD::class.java) -> true
            method.isAnnotationPresent(OPTIONS::class.java) -> true
            method.isAnnotationPresent(PATCH::class.java) -> true
            method.isAnnotationPresent(POST::class.java) -> true
            method.isAnnotationPresent(PUT::class.java) -> true
            else -> false
        }
    }

    private fun createEndpoint(resource: Class<*>, method: Method) = Endpoint(
            path = extractPath(resource, method),
            httpMethod = extractHttpMethod(method),
            pathParameters = extractPathParameters(method),
            queryParameters = extractQueryParameters(method),
            headerParameters = extractHeaderParameters(method),
            matrixParameters = extractMatrixParameters(method),
            produces = extractProduces(resource, method),
            consumes = extractConsumes(resource, method),
            deprecated = isEndpointDeprecated(method)
    )

    private fun extractPath(resource: Class<*>, method: Method): String {
        var pathOnClass = resource.getAnnotation(Path::class.java).value
        val pathOnFunction = if (method.isAnnotationPresent(Path::class.java)) {
            method.getAnnotation(Path::class.java).value
        } else {
            ""
        }

        if (!pathOnClass.startsWith("/")) {
            pathOnClass = "/$pathOnClass"
        }

        val combinedPath = "$pathOnClass/$pathOnFunction".replace(Regex("/+"), "/")

        return if (combinedPath.endsWith('/')) {
            combinedPath.substringBeforeLast('/')
        } else {
            combinedPath
        }
    }

    private fun extractHttpMethod(method: Method): HttpMethod {
        return when {
            method.isAnnotationPresent(DELETE::class.java) -> HttpMethod.DELETE
            method.isAnnotationPresent(GET::class.java) -> HttpMethod.GET
            method.isAnnotationPresent(HEAD::class.java) -> HttpMethod.HEAD
            method.isAnnotationPresent(OPTIONS::class.java) -> HttpMethod.OPTIONS
            method.isAnnotationPresent(PATCH::class.java) -> HttpMethod.PATCH
            method.isAnnotationPresent(POST::class.java) -> HttpMethod.POST
            method.isAnnotationPresent(PUT::class.java) -> HttpMethod.PUT
            else -> throw IllegalStateException("Unable to determine http method. Valid annotation not found.")
        }
    }

    private fun extractProduces(resource: Class<*>, method: Method): Set<String> {
        val annotationValue = when {
            method.isAnnotationPresent(Produces::class.java) -> method.getAnnotation(Produces::class.java).value.toSet()
            resource.isAnnotationPresent(Produces::class.java) -> resource.getAnnotation(Produces::class.java).value.toSet()
            else -> setOf("*/*")
        }

        return if (method.returnType.kotlin.isUnit()) {
            emptySet()
        } else {
            annotationValue
        }
    }

    private fun extractConsumes(resource: Class<*>, method: Method): Set<String> {
        val annotationValue = when {
            method.isAnnotationPresent(Consumes::class.java) -> method.getAnnotation(Consumes::class.java).value.toSet()
            resource.isAnnotationPresent(Consumes::class.java) -> resource.getAnnotation(Consumes::class.java).value.toSet()
            else -> setOf("*/*")
        }

        return if (containsRequestBody(method)) {
            annotationValue
        } else {
            emptySet()
        }
    }

    private fun containsRequestBody(method: Method): Boolean {
        return method.parameters
                .filterNot { it.isAnnotationPresent(BeanParam::class.java) }
                .filterNot { it.isAnnotationPresent(CookieParam::class.java) }
                .filterNot { it.isAnnotationPresent(DefaultValue::class.java) }
                .filterNot { it.isAnnotationPresent(Encoded::class.java) }
                .filterNot { it.isAnnotationPresent(FormParam::class.java) }
                .filterNot { it.isAnnotationPresent(HeaderParam::class.java) }
                .filterNot { it.isAnnotationPresent(MatrixParam::class.java) }
                .filterNot { it.isAnnotationPresent(PathParam::class.java) }
                .filterNot { it.isAnnotationPresent(QueryParam::class.java) }
                .isNotEmpty()
    }

    private fun extractQueryParameters(method: Method): Set<QueryParameter> {
        return method.parameters
                .filter { it.isAnnotationPresent(QueryParam::class.java) }
                .map { it.getAnnotation(QueryParam::class.java) }
                .map { (it as QueryParam).value }
                .map { QueryParameter(it, false) }
                .toSet()
    }

    private fun extractPathParameters(method: Method): Set<PathParameter> {
        return method.parameters
                .filter { it.isAnnotationPresent(PathParam::class.java) }
                .map { it.getAnnotation(PathParam::class.java) }
                .map { (it as PathParam).value }
                .map { PathParameter(it) }
                .toSet()
    }

    private fun extractHeaderParameters(method: Method): Set<HeaderParameter> {
        return method.parameters
                .filter { it.isAnnotationPresent(HeaderParam::class.java) }
                .map { it.getAnnotation(HeaderParam::class.java) }
                .map { (it as HeaderParam).value }
                .map { HeaderParameter(it) }
                .toSet()
    }

    private fun extractMatrixParameters(method: Method): Set<MatrixParameter> {
        return method.parameters
                .filter { it.isAnnotationPresent(MatrixParam::class.java) }
                .map { it.getAnnotation(MatrixParam::class.java) }
                .map { (it as MatrixParam).value }
                .map { MatrixParameter(it) }
                .toSet()
    }

    private fun isEndpointDeprecated(method: Method) =
            method.isAnnotationPresent(Deprecated::class.java)
                    || method.declaringClass.isAnnotationPresent(Deprecated::class.java)
}


================================================
FILE: jax-rs/src/main/resources/.gitemptydir
================================================


================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterConsumesTest.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HttpMethod.GET
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JaxRsConverterConsumesTest {

    @Test
    fun `single media type defined on class`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        consumes = setOf(
                                "application/json"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.consumes.singlemediatypeonclass").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `single media type defined on function`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        consumes = setOf(
                                "application/json"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.consumes.singlemediatypeonfunction").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `single media type without request body`() {
        // given
        val specification = setOf(
                Endpoint( "/todos", GET)
        )

        //when
        val result = JaxRsConverter("test.jaxrs.consumes.singlemediatypewithoutrequestbody").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `request body, but no annotation`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        consumes = setOf(
                                "*/*"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.consumes.noannotation").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `no request body, but other annotated parameter`() {
        // given
        val specification = setOf(
                Endpoint("/todos", GET)
        )

        //when
        val result = JaxRsConverter("test.jaxrs.consumes.singlemediatypewithoutrequestbodybutotherannotatedparameter").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `multiple media type defined on class`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        consumes = setOf(
                                "application/json",
                                "application/xml"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.consumes.multiplemediatypesonclass").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `multiple media type defined on function`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        consumes = setOf(
                                "application/json",
                                "application/xml"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.consumes.multiplemediatypesonfunction").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `function declaration overwrites class declaration`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        consumes = setOf(
                                "application/json",
                                "text/plain"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.consumes.functiondeclarationoverwritesclassdeclaration").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }
}

================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterDeprecationTest.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HttpMethod.GET
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JaxRsConverterDeprecationTest {

    @Test
    fun `no deprecation`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        deprecated =  false
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.deprecation.none").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `deprecated class`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        deprecated =  true
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.deprecation.onclass").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `deprecated function`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        deprecated = true
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.deprecation.onfunction").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }
}

================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterHeaderParametersTest.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HeaderParameter
import de.codecentric.hikaku.endpoints.HttpMethod.GET
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JaxRsConverterHeaderParameterTest {

    @Test
    fun `header parameter on function`() {
        //given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        headerParameters = setOf(
                                HeaderParameter("allow-cache")
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.headerparameters.onfunction").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }
}

================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterHttpMethodsTest.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HttpMethod.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JaxRsConverterHttpMethodsTest {

    @Test
    fun `extract all available http methods`() {
        //given
        val specification = setOf(
                Endpoint("/todos", GET),
                Endpoint("/todos", DELETE),
                Endpoint("/todos", POST),
                Endpoint("/todos", PUT),
                Endpoint("/todos", PATCH),
                Endpoint("/todos", OPTIONS),
                Endpoint("/todos", HEAD)
        )

        //when
        val result = JaxRsConverter("test.jaxrs.httpmethod.allmethods").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `resource class without http method annotation`() {
        //when
        val result = JaxRsConverter("test.jaxrs.httpmethod.noannotation").conversionResult

        //then
        assertThat(result).isEmpty()
    }
}

================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterMatrixParametersTest.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HttpMethod.GET
import de.codecentric.hikaku.endpoints.MatrixParameter
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JaxRsConverterMatrixParametersTest {

    @Test
    fun `matrix parameter on function`() {
        //given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        matrixParameters = setOf(
                                MatrixParameter("tag")
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.matrixparameters.onfunction").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }
}

================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterPackageDefinitionTest.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.converters.EndpointConverterException
import org.junit.jupiter.api.Test
import kotlin.test.assertFailsWith

class JaxRsConverterPackageDefinitionTest {

    @Test
    fun `invoking converter with empty string leads to EndpointConverterException`() {
        assertFailsWith<EndpointConverterException> {
            JaxRsConverter("").conversionResult
        }
    }

    @Test
    fun `invoking converter with blank string leads to EndpointConverterException`() {
        assertFailsWith<EndpointConverterException> {
            JaxRsConverter("     ").conversionResult
        }
    }
}

================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterPathParametersTest.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HttpMethod.GET
import de.codecentric.hikaku.endpoints.PathParameter
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JaxRsConverterPathParametersTest {

    @Test
    fun `no path parameter`() {
        //given
        val specification = setOf(
                Endpoint("/todos/{id}", GET)
        )

        //when
        val result = JaxRsConverter("test.jaxrs.pathparameters.nopathparameter").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `path parameter on function`() {
        //given
        val specification = setOf(
                Endpoint(
                        path = "/todos/{id}",
                        httpMethod = GET,
                        pathParameters = setOf(
                                PathParameter("id")
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.pathparameters.onfunction").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }
}

================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterPathTests.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HttpMethod.GET
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JaxRsConverterPathTests {

    @Test
    fun `simple path`() {
        // given
        val specification = setOf(
                Endpoint("/todos", GET)
        )

        //when
        val result = JaxRsConverter("test.jaxrs.path.simplepath").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `simple path without leading slash`() {
        // given
        val specification = setOf(
                Endpoint("/todos", GET)
        )

        //when
        val result = JaxRsConverter("test.jaxrs.path.simplepathwithoutleadingslash").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `nested path`() {
        // given
        val specification = setOf(
                Endpoint("/todo/list", GET)
        )

        //when
        val result = JaxRsConverter("test.jaxrs.path.nestedpath").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `nested path without leading slash`() {
        // given
        val specification = setOf(
                Endpoint("/todo/list", GET)
        )

        //when
        val result = JaxRsConverter("test.jaxrs.path.nestedpathwithoutleadingslash").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `resource class is not detected, if there is no Path annotation on class level`() {
        //when
        val result = JaxRsConverter("test.jaxrs.path.nopathonclass").conversionResult

        //then
        assertThat(result).isEmpty()
    }
}

================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterProducesTest.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HttpMethod.GET
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JaxRsConverterProducesTest {

    @Test
    fun `single media type defined on class`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        produces = setOf(
                                "application/json"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.produces.singlemediatypeonclass").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `single media type defined on function`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        produces = setOf(
                                "application/json"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.produces.singlemediatypeonfunction").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `single media type without return type`() {
        // given
        val specification = setOf(
                Endpoint( "/todos", GET)
        )

        //when
        val result = JaxRsConverter("test.jaxrs.produces.singlemediatypewithoutreturntype").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `return type, but no annotation`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        produces = setOf(
                                "*/*"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.produces.noannotation").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `multiple media type defined on class`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        produces = setOf(
                                "application/json",
                                "application/xml"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.produces.multiplemediatypesonclass").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `multiple media type defined on function`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        produces = setOf(
                                "application/json",
                                "application/xml"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.produces.multiplemediatypesonfunction").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }

    @Test
    fun `function declaration overwrites class declaration`() {
        // given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        produces = setOf(
                                "application/json",
                                "text/plain"
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.produces.functiondeclarationoverwritesclassdeclaration").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }
}

================================================
FILE: jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterQueryParameterTest.kt
================================================
package de.codecentric.hikaku.converters.jaxrs

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HttpMethod.GET
import de.codecentric.hikaku.endpoints.QueryParameter
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JaxRsConverterQueryParameterTest {

    @Test
    fun `query parameter on function`() {
        //given
        val specification = setOf(
                Endpoint(
                        path = "/todos",
                        httpMethod = GET,
                        queryParameters = setOf(
                                QueryParameter("filter")
                        )
                )
        )

        //when
        val result = JaxRsConverter("test.jaxrs.queryparameters.onfunction").conversionResult

        //then
        assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
    }
}

================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/consumes/functiondeclarationoverwritesclassdeclaration/FunctionDeclarationOverwritesClassDeclaration.kt
================================================
package test.jaxrs.consumes.functiondeclarationoverwritesclassdeclaration

import jakarta.ws.rs.Consumes
import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

data class Todo(val description: String = "")

@Path("/todos")
@Consumes("application/xml")
@Suppress("UNUSED_PARAMETER")
class FunctionDeclarationOverwritesClassDeclaration {

    @GET
    @Consumes("application/json", "text/plain")
    fun todo(todo: Todo) { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/consumes/multiplemediatypesonclass/MultipleMediaTypesOnClass.kt
================================================
package test.jaxrs.consumes.multiplemediatypesonclass

import jakarta.ws.rs.Consumes
import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

data class Todo(val description: String = "")

@Path("/todos")
@Consumes("application/json", "application/xml")
@Suppress("UNUSED_PARAMETER")
class MultipleMediaTypesOnClass {

    @GET
    fun todo(todo: Todo) {}
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/consumes/multiplemediatypesonfunction/MultipleMediaTypesOnFunction.kt
================================================
package test.jaxrs.consumes.multiplemediatypesonfunction

import jakarta.ws.rs.Consumes
import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

data class Todo(val description: String = "")

@Path("/todos")
@Suppress("UNUSED_PARAMETER")
class MultipleMediaTypesOnFunction {

    @GET
    @Consumes("application/json", "application/xml")
    fun todo(todo: Todo) { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/consumes/noannotation/NoAnnotation.kt
================================================
package test.jaxrs.consumes.noannotation

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

data class Todo(val description: String = "")

@Path("/todos")
@Suppress("UNUSED_PARAMETER")
class NoAnnotation {

    @GET
    fun todo(todo: Todo) { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypeonclass/ProducesOnClass.kt
================================================
package test.jaxrs.consumes.singlemediatypeonclass

import jakarta.ws.rs.Consumes
import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

data class Todo(val description: String = "")

@Path("/todos")
@Consumes("application/json")
@Suppress("UNUSED_PARAMETER")
class ProducesOnClass {

    @GET
    fun todo(todo: Todo) { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypeonfunction/ProducesOnFunction.kt
================================================
package test.jaxrs.consumes.singlemediatypeonfunction

import jakarta.ws.rs.Consumes
import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

data class Todo(val description: String = "")

@Path("/todos")
@Suppress("UNUSED_PARAMETER")
class ProducesOnFunction {

    @GET
    @Consumes("application/json")
    fun todo(todo: Todo) { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypewithoutrequestbody/SingleMediaTypeWithoutRequestBody.kt
================================================
package test.jaxrs.consumes.singlemediatypewithoutrequestbody

import jakarta.ws.rs.Consumes
import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

@Path("/todos")
class SingleMediaTypeWithoutRequestBody {

    @GET
    @Consumes("application/json")
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypewithoutrequestbodybutotherannotatedparameter/SingleMediaTypeWithoutRequestBodyButOtherAnnotatedParameter.kt
================================================
package test.jaxrs.consumes.singlemediatypewithoutrequestbodybutotherannotatedparameter

import jakarta.ws.rs.*

@Path("/todos")
@Suppress("UNUSED_PARAMETER")
class SingleMediaTypeWithoutRequestBodyButOtherAnnotatedParameter {

    @GET
    @Consumes("application/json")
    fun todo(@Encoded filter: String) { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/deprecation/none/NoDeprecation.kt
================================================
package test.jaxrs.deprecation.none

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

@Path("/todos")
class NoDeprecation {

    @GET
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/deprecation/onclass/DeprecationOnClass.kt
================================================
package test.jaxrs.deprecation.onclass

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

@Path("/todos")
@Deprecated("Test")
class DeprecationOnClass {

    @GET
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/deprecation/onfunction/DeprecationOnFunction.kt
================================================
package test.jaxrs.deprecation.onfunction

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

@Path("/todos")
class DeprecationOnFunction {

    @GET
    @Deprecated("Test")
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/headerparameters/onfunction/HeaderParametersOnFunction.kt
================================================
package test.jaxrs.headerparameters.onfunction

import jakarta.ws.rs.GET
import jakarta.ws.rs.HeaderParam
import jakarta.ws.rs.Path

@Path("/todos")
@Suppress("UNUSED_PARAMETER")
class HeaderParameterOnFunction {

    @GET
    fun todo(@HeaderParam("allow-cache") allowCache: String) { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/httpmethod/allmethods/AllHttpMethods.kt
================================================
package test.jaxrs.httpmethod.allmethods

import jakarta.ws.rs.*

@Path("/todos")
class AllHttpMethods {

    @GET
    fun getTodo() { }

    @DELETE
    fun deleteTodo() { }

    @POST
    fun postTodo() { }

    @PUT
    fun putTodos() { }

    @PATCH
    fun patchTodos() { }

    @OPTIONS
    fun optionsTodos() { }

    @HEAD
    fun headTodos() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/httpmethod/noannotation/NoAnnotation.kt
================================================
package test.jaxrs.httpmethod.noannotation

import jakarta.ws.rs.Path

@Path("")
class NoAnnotation


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/matrixparameters/onfunction/MatrixParametersOnFunction.kt
================================================
package test.jaxrs.matrixparameters.onfunction

import jakarta.ws.rs.GET
import jakarta.ws.rs.MatrixParam
import jakarta.ws.rs.Path

@Path("/todos")
@Suppress("UNUSED_PARAMETER")
class MatrixParameterOnFunction {

    @GET
    fun todo(@MatrixParam("tag") tag: String) { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/path/nestedpath/NestedPath.kt
================================================
package test.jaxrs.path.nestedpath

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

@Path("/todo")
class NestedPath {

    @GET
    @Path("/list")
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/path/nestedpathwithoutleadingslash/NestedPathWithoutLeadingSlash.kt
================================================
package test.jaxrs.path.nestedpathwithoutleadingslash

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

@Path("/todo")
class NestedPath {

    @GET
    @Path("list")
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/path/nopathonclass/NoPathAnnotationOnclass.kt
================================================
package test.jaxrs.path.nopathonclass

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

class NoPathAnnotationOnclass {

    @GET
    @Path("/todos")
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/path/simplepath/SimplePath.kt
================================================
package test.jaxrs.path.simplepath

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

@Path("/todos")
class SimplePath {

    @GET
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/path/simplepathwithoutleadingslash/SimplePathWithoutLeadingSlash.kt
================================================
package test.jaxrs.path.simplepathwithoutleadingslash

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

@Path("todos")
class SimplePathWithoutLeadingSlash {

    @GET
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/pathparameters/nopathparameter/NoPathParameter.kt
================================================
package test.jaxrs.pathparameters.nopathparameter

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

@Path("/todos")
class NoPathParameter {

    @GET
    @Path("/{id}")
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/pathparameters/onfunction/PathParameterOnFunction.kt
================================================
package test.jaxrs.pathparameters.onfunction

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
import jakarta.ws.rs.PathParam

@Path("/todos")
@Suppress("UNUSED_PARAMETER")
class PathParameterOnFunction {

    @GET
    @Path("/{id}")
    fun todo(@PathParam("id") id: String) { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/produces/functiondeclarationoverwritesclassdeclaration/FunctionDeclarationOverwritesClassDeclaration.kt
================================================
package test.jaxrs.produces.functiondeclarationoverwritesclassdeclaration

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
import jakarta.ws.rs.Produces

data class Todo(val description: String = "")

@Path("/todos")
@Produces("application/xml")
class FunctionDeclarationOverwritesClassDeclaration {

    @GET
    @Produces("application/json", "text/plain")
    fun todo() = Todo()
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/produces/multiplemediatypesonclass/MultipleMediaTypesOnClass.kt
================================================
package test.jaxrs.produces.multiplemediatypesonclass

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
import jakarta.ws.rs.Produces

data class Todo(val description: String = "")

@Path("/todos")
@Produces("application/json", "application/xml")
class MultipleMediaTypesOnClass {

    @GET
    fun todo() = Todo()
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/produces/multiplemediatypesonfunction/MultipleMediaTypesOnFunction.kt
================================================
package test.jaxrs.produces.multiplemediatypesonfunction

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
import jakarta.ws.rs.Produces

data class Todo(val description: String = "")

@Path("/todos")
class MultipleMediaTypesOnFunction {

    @GET
    @Produces("application/json", "application/xml")
    fun todo() = Todo()
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/produces/noannotation/NoAnnotation.kt
================================================
package test.jaxrs.produces.noannotation

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path

data class Todo(val description: String = "")

@Path("/todos")
class NoAnnotation {

    @GET
    fun todo() = Todo()
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/produces/singlemediatypeonclass/ProducesOnClass.kt
================================================
package test.jaxrs.produces.singlemediatypeonclass

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
import jakarta.ws.rs.Produces

data class Todo(val description: String = "")

@Path("/todos")
@Produces("application/json")
class ProducesOnClass {

    @GET
    fun todo() = Todo()
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/produces/singlemediatypeonfunction/ProducesOnFunction.kt
================================================
package test.jaxrs.produces.singlemediatypeonfunction

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
import jakarta.ws.rs.Produces

data class Todo(val description: String = "")

@Path("/todos")
class ProducesOnFunction {

    @GET
    @Produces("application/json")
    fun todo() = Todo()
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/produces/singlemediatypewithoutreturntype/SingleMediaTypeWithoutReturnType.kt
================================================
package test.jaxrs.produces.singlemediatypewithoutreturntype

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
import jakarta.ws.rs.Produces

@Path("/todos")
class SingleMediaTypeWithoutReturnType {

    @GET
    @Produces("application/json")
    fun todo() { }
}


================================================
FILE: jax-rs/src/test/kotlin/test/jaxrs/queryparameters/onfunction/QueryParameterOnFunction.kt
================================================
package test.jaxrs.queryparameters.onfunction

import jakarta.ws.rs.GET
import jakarta.ws.rs.Path
import jakarta.ws.rs.QueryParam

@Path("/todos")
@Suppress("UNUSED_PARAMETER")
class QueryParameterOnFunction {

    @GET
    fun todo(@QueryParam("filter") filter: String) { }
}


================================================
FILE: jax-rs/src/test/resources/.gitemptydir
================================================


================================================
FILE: micronaut/README.md
================================================
# hikaku - Micronaut

Converter for Micronaut.

## Feature Support

Please refer to the list of [all features](../docs/features.md). To check the feature support for this converter.

### Paths

+ Supports Controller annotation combined with empty HttpMethod annotation
  + _Example:_
```
@Controller("/todos")
class TodosController {

    @Get
    fun todos() { }
}
```

+ Supports Controller annotation combined with HttpMethod annotation
  + _Example:_
```
@Controller("/todo")
class TodosController {

    @Get("/list")
    fun todos() { }
}
```

+ Supports alias `uri` for HttpMethod annotation
  + _Example:_ `@Get(uri = "/todos")`
  
+ Supports paths with leading and non-leading slash on both Controller and HttpMethod annotation
  + _Examples:_
    + `@Controller("/todos")` and `@Controller("todos")`
    + `@Get("/todos")` and `@Get("todos")`

### Path parameters

+ Supports path parameter without annotation
  + _Examples:_
```
@Controller("/todos/{id}")
class TodosController {

    @Get
    fun todos(id: String) { }
}
```

+ Supports path parameter with annotation
  + _Examples:_
```
@Controller("/todos/{id}")
class TodosController {

    @Get
    fun todos(@PathVariable("id") otherName: String) { }
}
```

+ Supports using alias `name`
  + _Examples:_ `@PathVariable(name = "id") otherName: String`

### Query parameters

+ Supports query parameter without annotation
  + _Examples:_
```
@Controller("/todos")
class TodosController {

    @Get
    fun todos(filter: String) { }
}
```

+ Supports query parameter with annotation
  + _Examples:_
```
@Controller("/todos")
class TodosController {

    @Get
    fun todos(@QueryValue("filter") filter: String) { }
}
```

+ Supports setting the parameter _required_ or _optional_ based on the existence of a default value
  + _Examples:_ `@QueryValue("filter", defaultValue = "all") filter: String`

### Header parameters

+ Supports required header parameter
  + _Examples:_
```
@Controller("/todos")
class TodosController {

    @Get
    fun todos(@Header("allow-cache") otherName: String) { }
}
```

+ Supports optional header parameter based on the existence of a default value
  + _Examples:_ `@Header("allow-cache", defaultValue = "true") otherName: String`
  
### Consumes

+ Supports default media type `application/json`

+ Supports single and multiple media type declarations in Controller annotation

+ Supports Consumes annotation with single and multiple media type declarations on class and function

+ Supports Consumes annotation overriding the value of the Controller annotation

### Produces

+ Supports default media type `application/json`

+ Supports single and multiple media type declarations in Controller annotation

+ Supports Produces annotation with single and multiple media type declarations on class and function

+ Supports Produces annotation overriding the value of the Controller annotation

## Usage

Instantiate the converter with a package name which will be scanned recursively for controllers.

_Example_: `MicronautConverter("de.codecentric.hikaku")`

================================================
FILE: micronaut/build.gradle
================================================
group = 'de.codecentric.hikaku'
archivesBaseName = 'hikaku-micronaut'

dependencies {
  api project(':core')
  api 'io.micronaut:micronaut-http:3.0.0'
}

uploadArchives {
  repositories {
    mavenDeployer {
      pom.project {
        name = 'hikaku-micronaut'
        description = 'A library that tests if the implementation of a REST-API meets its specification. This module contains a converter for micronaut implementations.'
      }
    }
  }
}


================================================
FILE: micronaut/src/main/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverter.kt
================================================
package de.codecentric.hikaku.converters.micronaut

import de.codecentric.hikaku.SupportedFeatures
import de.codecentric.hikaku.SupportedFeatures.Feature
import de.codecentric.hikaku.converters.AbstractEndpointConverter
import de.codecentric.hikaku.converters.ClassLocator
import de.codecentric.hikaku.converters.EndpointConverterException
import de.codecentric.hikaku.endpoints.*
import de.codecentric.hikaku.extensions.isUnit
import io.micronaut.http.annotation.*
import java.lang.reflect.Method
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.jvm.kotlinFunction

class MicronautConverter(private val packageName: String) : AbstractEndpointConverter() {

    override val supportedFeatures = SupportedFeatures(
        Feature.QueryParameters,
        Feature.PathParameters,
        Feature.HeaderParameters,
        Feature.Produces,
        Feature.Consumes,
        Feature.Deprecation
    )

    override fun convert(): Set<Endpoint> {
        if (packageName.isBlank()) {
            throw EndpointConverterException("Package name must not be blank.")
        }

        return ClassLocator.getClasses(packageName)
                .filter { it.getAnnotation(Controller::class.java) != null }
                .flatMap { extractEndpoints(it) }
                .toSet()
    }

    private fun extractEndpoints(resource: Class<*>): List<Endpoint> {
        return resource.methods
                .filter { isHttpMethodAnnotationPresent(it) }
                .map { createEndpoint(resource, it) }
    }

    private fun isHttpMethodAnnotationPresent(method: Method): Boolean {
        return when {
            method.isAnnotationPresent(Delete::class.java) -> true
            method.isAnnotationPresent(Get::class.java) -> true
            method.isAnnotationPresent(Head::class.java) -> true
            method.isAnnotationPresent(Options::class.java) -> true
            method.isAnnotationPresent(Patch::class.java) -> true
            method.isAnnotationPresent(Post::class.java) -> true
            method.isAnnotationPresent(Put::class.java) -> true
            else -> false
        }
    }

    private fun createEndpoint(resource: Class<*>, method: Method): Endpoint {
        val path = extractPath(resource, method)

        return Endpoint(
                path = path,
                httpMethod = extractHttpMethod(method),
                queryParameters = extractQueryParameters(path, method),
                pathParameters = extractPathParameters(path, method),
                headerParameters = extractHeaderParameters(method),
                consumes = extractConsumes(resource, method),
                produces = extractProduces(resource, method),
                deprecated = isEndpointDeprecated(method)
        )
    }

    private fun extractProduces(resource: Class<*>, method: Method): Set<String> {
        val methodHasNoReturnType = method.returnType.kotlin.isUnit()

        if (methodHasNoReturnType) {
            return emptySet()
        }

        val mediaTypesOnFunction = method.kotlinFunction
                ?.annotations
                ?.filterIsInstance<Produces>()
                ?.flatMap { it.value.map { entry -> entry } }
                ?.toSet()
                .orEmpty()

        if (mediaTypesOnFunction.isNotEmpty()) {
            return mediaTypesOnFunction
        }

        val mediaTypesOnControllerByConsumesAnnotation = resource.getAnnotation(Produces::class.java)
                ?.value
                ?.toSet()
                .orEmpty()

        if (mediaTypesOnControllerByConsumesAnnotation.isNotEmpty()) {
            return mediaTypesOnControllerByConsumesAnnotation
        }

        val mediaTypesDefinedByControllerAnnotation = resource.getAnnotation(Controller::class.java)
                .produces
                .toSet()

        if (mediaTypesDefinedByControllerAnnotation.isNotEmpty()) {
            return mediaTypesDefinedByControllerAnnotation
        }

        return setOf("application/json")
    }

    private fun extractConsumes(resource: Class<*>, method: Method): Set<String> {
        val methodAwaitsPayload = method.kotlinFunction
                ?.parameters
                ?.any { it.findAnnotation<Body>() != null }
                ?: false

        if (!methodAwaitsPayload) {
            return emptySet()
        }

        val mediaTypesOnFunction = method.kotlinFunction
                ?.annotations
                ?.filterIsInstance<Consumes>()
                ?.flatMap { it.value.map { entry -> entry } }
                ?.toSet()
                .orEmpty()

        if (mediaTypesOnFunction.isNotEmpty()) {
            return mediaTypesOnFunction
        }

        val mediaTypesOnControllerByConsumesAnnotation = resource.getAnnotation(Consumes::class.java)
                ?.value
                ?.toSet()
                .orEmpty()

        if (mediaTypesOnControllerByConsumesAnnotation.isNotEmpty()) {
            return mediaTypesOnControllerByConsumesAnnotation
        }

        val mediaTypesDefinedByControllerAnnotation = resource.getAnnotation(Controller::class.java)
                .consumes
                .toSet()

        if (mediaTypesDefinedByControllerAnnotation.isNotEmpty()) {
            return mediaTypesDefinedByControllerAnnotation
        }

        return setOf("application/json")
    }

    private fun extractPath(resource: Class<*>, method: Method): String {
        var pathOnClass = resource.getAnnotation(Controller::class.java).value
        val pathOnFunction = when {
            method.isAnnotationPresent(Delete::class.java) -> method.getAnnotation(Delete::class.java).value
            method.isAnnotationPresent(Get::class.java) -> method.getAnnotation(Get::class.java).value
            method.isAnnotationPresent(Head::class.java) -> method.getAnnotation(Head::class.java).value
            method.isAnnotationPresent(Options::class.java) -> method.getAnnotation(Options::class.java).value
            method.isAnnotationPresent(Patch::class.java) -> method.getAnnotation(Patch::class.java).value
            method.isAnnotationPresent(Post::class.java) -> method.getAnnotation(Post::class.java).value
            method.isAnnotationPresent(Put::class.java) -> method.getAnnotation(Put::class.java).value
            else -> ""
        }

        if (!pathOnClass.startsWith("/")) {
            pathOnClass = "/$pathOnClass"
        }

        val combinedPath = "$pathOnClass/$pathOnFunction".replace(Regex("/+"), "/")

        return if (combinedPath.endsWith('/')) {
            combinedPath.substringBeforeLast('/')
        } else {
            combinedPath
        }
    }

    private fun extractHttpMethod(method: Method): HttpMethod {
        return when {
            method.isAnnotationPresent(Delete::class.java) -> HttpMethod.DELETE
            method.isAnnotationPresent(Get::class.java) -> HttpMethod.GET
            method.isAnnotationPresent(Head::class.java) -> HttpMethod.HEAD
            method.isAnnotationPresent(Options::class.java) -> HttpMethod.OPTIONS
            method.isAnnotationPresent(Patch::class.java) -> HttpMethod.PATCH
            method.isAnnotationPresent(Post::class.java) -> HttpMethod.POST
            method.isAnnotationPresent(Put::class.java) -> HttpMethod.PUT
            else -> throw IllegalStateException("Unable to determine http method. Valid annotation not found.")
        }
    }

    private fun extractQueryParameters(path: String, method: Method): Set<QueryParameter> {
        val queryParameters = method.parameters
                .filter { it.isAnnotationPresent(QueryValue::class.java) }
                .map { it.getAnnotation(QueryValue::class.java) }
                .map { it as QueryValue }
                .map { QueryParameter(it.value, it.defaultValue.isBlank()) }
                .toMutableSet()


        val queryParameterWithoutAnnotation = methodParametersWithoutAnnotation(method).filterNot { templatesInPath(path).contains(it) }
                .filterNotNull()
                .map { QueryParameter(it, false) }
                .toSet()

        queryParameters.addAll(queryParameterWithoutAnnotation)

        return queryParameters
    }

    private fun extractPathParameters(path: String, method: Method): Set<PathParameter> {
        val parameters = method.parameters
                .filter { it.isAnnotationPresent(PathVariable::class.java) }
                .map { it.getAnnotation(PathVariable::class.java) as PathVariable }
                .map {
                    val pathParameter = if (it.value.isNotBlank()) {
                        it.value
                    } else {
                        it.name
                    }

                    PathParameter(pathParameter)
                }
                .toMutableSet()

        val pathParametersWithoutAnnotation = templatesInPath(path)
                .filter { methodParametersWithoutAnnotation(method).contains(it) }
                .map { PathParameter(it) }
                .toSet()

        parameters.addAll(pathParametersWithoutAnnotation)

        return parameters
    }

    private fun methodParametersWithoutAnnotation(method: Method) = method.kotlinFunction
        ?.parameters
        ?.filter { it.annotations.isEmpty() }
        ?.map { it.name }
        .orEmpty()

    private fun templatesInPath(path: String) = Regex("\\{.+\\}").findAll(path)
        .map { it.value }
        .map { it.removePrefix("{") }
        .map { it.removeSuffix("}") }
        .toSet()

    private fun extractHeaderParameters(method: Method): Set<HeaderParameter> {
        return method.parameters
                .filter { it.isAnnotationPresent(Header::class.java) }
                .map { it.getAnnotation(Header::class.java) }
                .map { it as Header }
                .map { HeaderParameter(it.value, it.defaultValue.isBlank()) }
                .toSet()
    }

    private fun isEndpointDeprecated(method: Method) =
            method.isAnnotationPresent(Deprecated::class.java)
                    || method.declaringClass.isAnnotationPresent(Deprecated::class.java)
}


================================================
FILE: micronaut/src/main/resources/.gitemptydir
================================================


================================================
FILE: micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterConsumesTest.kt
================================================
package de.codecentric.hikaku.converters.micronaut

import de.codecentric.hikaku.endpoints.Endpoint
import de.codecentric.hikaku.endpoints.HttpMethod.POST
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test

class MicronautConverterConsumesTest {

    @Nested
    inner class DeclaredByControllerOnClass {

        @Test
        fun `single media type`() {
            //given
            val specification = setOf(
                    Endpoint(
                            path = "/todos",
                            httpMethod = POST,
                            consumes = setOf(
                                "text/plain"
                            )
                    )
            )

            //when
            val result = MicronautConverter("test.micronaut.consumes.onclass.onlycontroller.singlemediatype").conversionResult

            //then
            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
        }

        @Test
        fun `multiple media types`() {
            //given
            val specification = setOf(
                    Endpoint(
                            path = "/todos",
                            httpMethod = POST,
                            consumes = setOf(
                                    "text/plain",
                                    "application/xml"
                            )
                    )
            )

            //when
            val result = MicronautConverter("test.micronaut.consumes.onclass.onlycontroller.multiplemediatypes").conversionResult

            //then
            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
        }
    }

    @Nested
    inner class ConsumesOnClassOverridesController {

        @Test
        fun `single media type`() {
            //given
            val specification = setOf(
                    Endpoint(
                            path = "/todos",
                            httpMethod = POST,
                            consumes = setOf(
                                    "application/xml"
                            )
                    )
            )

            //when
            val result = MicronautConverter("test.micronaut.consumes.onclass.consumesoverridescontroller.singlemediatype").conversionResult

            //then
            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
        }

        @Test
        fun `multiple media types`() {
            //given
            val specification = setOf(
                    Endpoint(
                            path = "/todos",
                            httpMethod = POST,
                            consumes = setOf(
                                    "application/json",
                                    "application/pdf"
                            )
                    )
            )

            //when
            val result = MicronautConverter("test.micronaut.consumes.onclass.consumesoverridescontroller.multiplemediatypes").conversionResult

            //then
            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
        }
    }

    @Nested
    inner class DeclaredByConsumesOnFunction {

        @Test
        fun `single media type`() {
            //given
            val specification = setOf(
                    Endpoint(
                            path = "/todos",
                            httpMethod = POST,
                            consumes = setOf(
                                    "text/plain"
                            )
                    )
            )

            //when
            val result = MicronautConverter("test.micronaut.consumes.onfunction.onlyconsumes.singlemediatype").conversionResult

            //then
            assertThat(result).containsExactlyInAnyOrderElementsOf(specification)
        }

        @Test
        fun `multiple media types`() {
            //given
            val specification = setOf(
                    Endpoint(
                            path = "/todos",
                            httpMethod = POST,
                            consumes = setOf(
                                    "text/plain",
                                    "applic
Download .txt
gitextract_0lqdq178/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── feature_request.md
│   │   └── question.md
│   └── dependabot.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.gradle
├── core/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               ├── Hikaku.kt
│       │   │               ├── HikakuConfig.kt
│       │   │               ├── SupportedFeatures.kt
│       │   │               ├── converters/
│       │   │               │   ├── AbstractEndpointConverter.kt
│       │   │               │   ├── ClassLocator.kt
│       │   │               │   ├── EndpointConverter.kt
│       │   │               │   └── EndpointConverterException.kt
│       │   │               ├── endpoints/
│       │   │               │   ├── Endpoint.kt
│       │   │               │   ├── HeaderParameter.kt
│       │   │               │   ├── HttpMethod.kt
│       │   │               │   ├── MatrixParameter.kt
│       │   │               │   ├── PathParameter.kt
│       │   │               │   └── QueryParameter.kt
│       │   │               ├── extensions/
│       │   │               │   ├── ClassExtensions.kt
│       │   │               │   ├── FileExtensions.kt
│       │   │               │   └── PathExtensions.kt
│       │   │               └── reporters/
│       │   │                   ├── CommandLineReporter.kt
│       │   │                   ├── MatchResult.kt
│       │   │                   ├── NoOperationReporter.kt
│       │   │                   └── Reporter.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   └── de/
│           │       └── codecentric/
│           │           └── hikaku/
│           │               ├── HikakuTest.kt
│           │               └── extensions/
│           │                   ├── ClassExtensionsTest.kt
│           │                   ├── FileExtensionsTest.kt
│           │                   └── PathExtensionsTest.kt
│           └── resources/
│               └── test_file.txt
├── docs/
│   ├── config.md
│   └── features.md
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── install-jdk.sh
├── jax-rs/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── jaxrs/
│       │   │                       └── JaxRsConverter.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   ├── de/
│           │   │   └── codecentric/
│           │   │       └── hikaku/
│           │   │           └── converters/
│           │   │               └── jaxrs/
│           │   │                   ├── JaxRsConverterConsumesTest.kt
│           │   │                   ├── JaxRsConverterDeprecationTest.kt
│           │   │                   ├── JaxRsConverterHeaderParametersTest.kt
│           │   │                   ├── JaxRsConverterHttpMethodsTest.kt
│           │   │                   ├── JaxRsConverterMatrixParametersTest.kt
│           │   │                   ├── JaxRsConverterPackageDefinitionTest.kt
│           │   │                   ├── JaxRsConverterPathParametersTest.kt
│           │   │                   ├── JaxRsConverterPathTests.kt
│           │   │                   ├── JaxRsConverterProducesTest.kt
│           │   │                   └── JaxRsConverterQueryParameterTest.kt
│           │   └── test/
│           │       └── jaxrs/
│           │           ├── consumes/
│           │           │   ├── functiondeclarationoverwritesclassdeclaration/
│           │           │   │   └── FunctionDeclarationOverwritesClassDeclaration.kt
│           │           │   ├── multiplemediatypesonclass/
│           │           │   │   └── MultipleMediaTypesOnClass.kt
│           │           │   ├── multiplemediatypesonfunction/
│           │           │   │   └── MultipleMediaTypesOnFunction.kt
│           │           │   ├── noannotation/
│           │           │   │   └── NoAnnotation.kt
│           │           │   ├── singlemediatypeonclass/
│           │           │   │   └── ProducesOnClass.kt
│           │           │   ├── singlemediatypeonfunction/
│           │           │   │   └── ProducesOnFunction.kt
│           │           │   ├── singlemediatypewithoutrequestbody/
│           │           │   │   └── SingleMediaTypeWithoutRequestBody.kt
│           │           │   └── singlemediatypewithoutrequestbodybutotherannotatedparameter/
│           │           │       └── SingleMediaTypeWithoutRequestBodyButOtherAnnotatedParameter.kt
│           │           ├── deprecation/
│           │           │   ├── none/
│           │           │   │   └── NoDeprecation.kt
│           │           │   ├── onclass/
│           │           │   │   └── DeprecationOnClass.kt
│           │           │   └── onfunction/
│           │           │       └── DeprecationOnFunction.kt
│           │           ├── headerparameters/
│           │           │   └── onfunction/
│           │           │       └── HeaderParametersOnFunction.kt
│           │           ├── httpmethod/
│           │           │   ├── allmethods/
│           │           │   │   └── AllHttpMethods.kt
│           │           │   └── noannotation/
│           │           │       └── NoAnnotation.kt
│           │           ├── matrixparameters/
│           │           │   └── onfunction/
│           │           │       └── MatrixParametersOnFunction.kt
│           │           ├── path/
│           │           │   ├── nestedpath/
│           │           │   │   └── NestedPath.kt
│           │           │   ├── nestedpathwithoutleadingslash/
│           │           │   │   └── NestedPathWithoutLeadingSlash.kt
│           │           │   ├── nopathonclass/
│           │           │   │   └── NoPathAnnotationOnclass.kt
│           │           │   ├── simplepath/
│           │           │   │   └── SimplePath.kt
│           │           │   └── simplepathwithoutleadingslash/
│           │           │       └── SimplePathWithoutLeadingSlash.kt
│           │           ├── pathparameters/
│           │           │   ├── nopathparameter/
│           │           │   │   └── NoPathParameter.kt
│           │           │   └── onfunction/
│           │           │       └── PathParameterOnFunction.kt
│           │           ├── produces/
│           │           │   ├── functiondeclarationoverwritesclassdeclaration/
│           │           │   │   └── FunctionDeclarationOverwritesClassDeclaration.kt
│           │           │   ├── multiplemediatypesonclass/
│           │           │   │   └── MultipleMediaTypesOnClass.kt
│           │           │   ├── multiplemediatypesonfunction/
│           │           │   │   └── MultipleMediaTypesOnFunction.kt
│           │           │   ├── noannotation/
│           │           │   │   └── NoAnnotation.kt
│           │           │   ├── singlemediatypeonclass/
│           │           │   │   └── ProducesOnClass.kt
│           │           │   ├── singlemediatypeonfunction/
│           │           │   │   └── ProducesOnFunction.kt
│           │           │   └── singlemediatypewithoutreturntype/
│           │           │       └── SingleMediaTypeWithoutReturnType.kt
│           │           └── queryparameters/
│           │               └── onfunction/
│           │                   └── QueryParameterOnFunction.kt
│           └── resources/
│               └── .gitemptydir
├── micronaut/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── micronaut/
│       │   │                       └── MicronautConverter.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   ├── de/
│           │   │   └── codecentric/
│           │   │       └── hikaku/
│           │   │           └── converters/
│           │   │               └── micronaut/
│           │   │                   ├── MicronautConverterConsumesTest.kt
│           │   │                   ├── MicronautConverterDeprecationTest.kt
│           │   │                   ├── MicronautConverterHeaderParameterTest.kt
│           │   │                   ├── MicronautConverterPackageDefinitionTest.kt
│           │   │                   ├── MicronautConverterPathParameterTest.kt
│           │   │                   ├── MicronautConverterPathTest.kt
│           │   │                   ├── MicronautConverterProducesTest.kt
│           │   │                   └── MicronautConverterQueryParameterTest.kt
│           │   └── test/
│           │       └── micronaut/
│           │           ├── Todo.kt
│           │           ├── consumes/
│           │           │   ├── default/
│           │           │   │   └── ConsumesDefaultMediaTypeTestController.kt
│           │           │   ├── onclass/
│           │           │   │   ├── consumesoverridescontroller/
│           │           │   │   │   ├── multiplemediatypes/
│           │           │   │   │   │   └── ConsumesMultipleMediaTypesTestController.kt
│           │           │   │   │   └── singlemediatype/
│           │           │   │   │       └── ConsumesSingleMediaTypeTestController.kt
│           │           │   │   └── onlycontroller/
│           │           │   │       ├── multiplemediatypes/
│           │           │   │       │   └── ConsumesMultipleMediaTypesTestController.kt
│           │           │   │       └── singlemediatype/
│           │           │   │           └── ConsumesSingleMediaTypeTestController.kt
│           │           │   └── onfunction/
│           │           │       ├── consumesoverridescontroller/
│           │           │       │   ├── multiplemediatypes/
│           │           │       │   │   └── ConsumesMultipleMediaTypesTestController.kt
│           │           │       │   └── singlemediatype/
│           │           │       │       └── ConsumesSingleMediaTypeTestController.kt
│           │           │       └── onlyconsumes/
│           │           │           ├── multiplemediatypes/
│           │           │           │   └── ConsumesMultipleMediaTypesTestController.kt
│           │           │           └── singlemediatype/
│           │           │               └── ConsumesSingleMediaTypeTestController.kt
│           │           ├── deprecation/
│           │           │   ├── none/
│           │           │   │   └── NoDeprecation.kt
│           │           │   ├── onclass/
│           │           │   │   └── DeprecationOnClass.kt
│           │           │   └── onfunction/
│           │           │       └── DeprecationOnFunction.kt
│           │           ├── headerparameters/
│           │           │   ├── optional/
│           │           │   │   └── HeaderParameterTestController.kt
│           │           │   └── required/
│           │           │       └── HeaderParameterTestController.kt
│           │           ├── path/
│           │           │   ├── combinedcontrollerandhttpmethodannotation/
│           │           │   │   ├── delete/
│           │           │   │   │   └── CombinedControllerAnnotationWithDeletePathTestController.kt
│           │           │   │   ├── get/
│           │           │   │   │   └── CombinedControllerAnnotationWithGetPathTestController.kt
│           │           │   │   ├── head/
│           │           │   │   │   └── CombinedControllerAnnotationWithHeadPathTestController.kt
│           │           │   │   ├── options/
│           │           │   │   │   └── CombinedControllerAnnotationWithOptionsPathTestController.kt
│           │           │   │   ├── patch/
│           │           │   │   │   └── CombinedControllerAnnotationWithPatchPathTestController.kt
│           │           │   │   ├── post/
│           │           │   │   │   └── CombinedControllerAnnotationWithPostPathTestController.kt
│           │           │   │   └── put/
│           │           │   │       └── CombinedControllerAnnotationWithPutPathTestController.kt
│           │           │   ├── firstpathsegmentwithoutleadingslash/
│           │           │   │   └── FirstPathSegmentWithoutLeadingSlashTestController.kt
│           │           │   ├── innerpathsegmentwithoutleadingslash/
│           │           │   │   └── InnerPathSegmentWithoutLeadingSlashTestController.kt
│           │           │   ├── nohttpmethodannotation/
│           │           │   │   └── NoHttpMethodAnnotationTestController.kt
│           │           │   └── onlycontrollerannotation/
│           │           │       ├── delete/
│           │           │       │   └── OnlyControllerAnnotationWithDeletePathTestController.kt
│           │           │       ├── get/
│           │           │       │   └── OnlyControllerAnnotationWithGetPathTestController.kt
│           │           │       ├── head/
│           │           │       │   └── OnlyControllerAnnotationWithHeadPathTestController.kt
│           │           │       ├── options/
│           │           │       │   └── OnlyControllerAnnotationWithOptionsPathTestController.kt
│           │           │       ├── patch/
│           │           │       │   └── OnlyControllerAnnotationWithPatchPathTestController.kt
│           │           │       ├── post/
│           │           │       │   └── OnlyControllerAnnotationWithPostPathTestController.kt
│           │           │       └── put/
│           │           │           └── OnlyControllerAnnotationWithPutPathTestController.kt
│           │           ├── pathparameters/
│           │           │   ├── annotation/
│           │           │   │   ├── name/
│           │           │   │   │   └── PathParameterDefinedByAnnotationTestController.kt
│           │           │   │   └── value/
│           │           │   │       └── PathParameterDefinedByAnnotationTestController.kt
│           │           │   └── variable/
│           │           │       └── PathParameterDefinedByVariableNameTestController.kt
│           │           ├── produces/
│           │           │   ├── default/
│           │           │   │   └── DefaultTestController.kt
│           │           │   ├── onclass/
│           │           │   │   ├── onlycontroller/
│           │           │   │   │   ├── multiplemediatypes/
│           │           │   │   │   │   └── ProducesMultipleMediaTypesTestController.kt
│           │           │   │   │   └── singlemediatype/
│           │           │   │   │       └── ProducesSingleMediaTypeTestController.kt
│           │           │   │   └── producesoverridescontroller/
│           │           │   │       ├── multiplemediatypes/
│           │           │   │       │   └── ProducesMultipleMediaTypesTestController.kt
│           │           │   │       └── singlemediatype/
│           │           │   │           └── ProducesSingleMediaTypeTestController.kt
│           │           │   └── onfunction/
│           │           │       ├── onlyproduces/
│           │           │       │   ├── multiplemediatypes/
│           │           │       │   │   └── ProducesMultipleMediaTypesTestController.kt
│           │           │       │   └── singlemediatype/
│           │           │       │       └── ProducesSingleMediaTypeTestController.kt
│           │           │       └── producesoverridescontroller/
│           │           │           ├── multiplemediatypes/
│           │           │           │   └── ProducesMultipleMediaTypesTestController.kt
│           │           │           └── singlemediatype/
│           │           │               └── ProducesSingleMediaTypeTestController.kt
│           │           └── queryparameters/
│           │               ├── optional/
│           │               │   └── QueryParameterTestController.kt
│           │               └── required/
│           │                   ├── annotation/
│           │                   │   └── QueryParameterTestController.kt
│           │                   └── withoutannotation/
│           │                       └── QueryParameterTestController.kt
│           └── resources/
│               └── resources/
│                   └── .gitemptydir
├── openapi/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── openapi/
│       │   │                       ├── OpenApiConverter.kt
│       │   │                       ├── extensions/
│       │   │                       │   ├── PathItemExtensions.kt
│       │   │                       │   └── ReferencedSchema.kt
│       │   │                       └── extractors/
│       │   │                           ├── ConsumesExtractor.kt
│       │   │                           ├── HeaderParameterExtractor.kt
│       │   │                           ├── PathParameterExtractor.kt
│       │   │                           ├── ProducesExtractor.kt
│       │   │                           └── QueryParameterExtractor.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   └── de/
│           │       └── codecentric/
│           │           └── hikaku/
│           │               └── converters/
│           │                   └── openapi/
│           │                       ├── OpenApiConverterConsumesTest.kt
│           │                       ├── OpenApiConverterDeprecationTest.kt
│           │                       ├── OpenApiConverterEndpointTest.kt
│           │                       ├── OpenApiConverterHeaderParameterTest.kt
│           │                       ├── OpenApiConverterInvalidInputTest.kt
│           │                       ├── OpenApiConverterPathParameterTest.kt
│           │                       ├── OpenApiConverterProducesTest.kt
│           │                       └── OpenApiConverterQueryParameterTest.kt
│           └── resources/
│               ├── consumes/
│               │   ├── consumes_inline.yaml
│               │   └── consumes_requestbody_in_components.yaml
│               ├── deprecation/
│               │   ├── deprecation_none.yaml
│               │   └── deprecation_operation.yaml
│               ├── endpoints/
│               │   ├── endpoints_all_http_methods.yaml
│               │   ├── endpoints_two_different_paths.yaml
│               │   └── endpoints_two_nested_paths.yaml
│               ├── header_parameter/
│               │   ├── common_header_parameter_in_components.yaml
│               │   ├── common_header_parameter_inline.yaml
│               │   ├── header_parameter_in_components.yaml
│               │   └── header_parameter_inline.yaml
│               ├── invalid_input/
│               │   ├── empty_file.yaml
│               │   ├── syntax_error.yaml
│               │   └── whitespaces_only_file.yaml
│               ├── path_parameter/
│               │   ├── common_path_parameter_in_components.yaml
│               │   ├── common_path_parameter_inline.yaml
│               │   ├── path_parameter_in_components.yaml
│               │   └── path_parameter_inline.yaml
│               ├── produces/
│               │   ├── produces_inline.yaml
│               │   ├── produces_no_content_type.yaml
│               │   ├── produces_response_in_components.yaml
│               │   └── produces_with_default.yaml
│               └── query_parameter/
│                   ├── common_query_parameter_in_components.yaml
│                   ├── common_query_parameter_inline.yaml
│                   ├── query_parameter_in_components.yaml
│                   └── query_parameter_inline.yaml
├── raml/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── raml/
│       │   │                       ├── RamlConverter.kt
│       │   │                       └── extensions/
│       │   │                           ├── MethodExtensions.kt
│       │   │                           └── ResourceExtensions.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   └── de/
│           │       └── codecentric/
│           │           └── hikaku/
│           │               └── converters/
│           │                   └── raml/
│           │                       ├── RamlConverterConsumesTest.kt
│           │                       ├── RamlConverterDeprecationTest.kt
│           │                       ├── RamlConverterHeaderParameterTest.kt
│           │                       ├── RamlConverterHttpMethodTest.kt
│           │                       ├── RamlConverterInvalidInputTest.kt
│           │                       ├── RamlConverterPathParameterTest.kt
│           │                       ├── RamlConverterPathTest.kt
│           │                       ├── RamlConverterProducesTest.kt
│           │                       └── RamlConverterQueryParameterTest.kt
│           └── resources/
│               ├── consumes/
│               │   ├── method_declaration_overwrites_default.raml
│               │   ├── multiple_default_media_types.raml
│               │   ├── multiple_method_declarations.raml
│               │   ├── no_media_type.raml
│               │   ├── single_default_media_type.raml
│               │   └── single_method_declaration.raml
│               ├── deprecation/
│               │   ├── none.raml
│               │   ├── on_method.raml
│               │   └── on_resource.raml
│               ├── header_parameter.raml
│               ├── http_method/
│               │   ├── http_methods.raml
│               │   └── path_without_http_method.raml
│               ├── invalid_input/
│               │   ├── different_extension.css
│               │   ├── empty_file.raml
│               │   ├── invalid_raml_version.raml
│               │   ├── syntax_error.raml
│               │   └── whitespaces_only_file.raml
│               ├── path/
│               │   ├── nested_path.raml
│               │   ├── nested_path_single_entry.raml
│               │   └── simple_path.raml
│               ├── path_parameter/
│               │   ├── nested_path_parameter.raml
│               │   └── simple_path_parameter.raml
│               ├── produces/
│               │   ├── method_declaration_overwrites_default.raml
│               │   ├── multiple_default_media_types.raml
│               │   ├── multiple_method_declarations.raml
│               │   ├── no_media_type.raml
│               │   ├── single_default_media_type.raml
│               │   └── single_method_declaration.raml
│               └── query_parameter/
│                   └── query_parameter.raml
├── settings.gradle
├── spring/
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── kotlin/
│       │   │   └── de/
│       │   │       └── codecentric/
│       │   │           └── hikaku/
│       │   │               └── converters/
│       │   │                   └── spring/
│       │   │                       ├── SpringConverter.kt
│       │   │                       └── extensions/
│       │   │                           ├── ConsumesExtension.kt
│       │   │                           ├── DeprecationExtension.kt
│       │   │                           ├── HeaderParametersSpringExtension.kt
│       │   │                           ├── HttpMethodsSpringExtension.kt
│       │   │                           ├── MatrixParametersSpringExtension.kt
│       │   │                           ├── PathParametersSpringExtension.kt
│       │   │                           ├── PathsSpringExtension.kt
│       │   │                           ├── ProducesSpringExtension.kt
│       │   │                           └── QueryParametersSpringExtension.kt
│       │   └── resources/
│       │       └── .gitemptydir
│       └── test/
│           ├── kotlin/
│           │   └── de/
│           │       └── codecentric/
│           │           └── hikaku/
│           │               └── converters/
│           │                   └── spring/
│           │                       ├── consumes/
│           │                       │   ├── ConsumesTestController.kt
│           │                       │   └── SpringConverterConsumesTest.kt
│           │                       ├── deprecation/
│           │                       │   ├── DeprecationTestController.kt
│           │                       │   └── SpringConverterDeprecationTest.kt
│           │                       ├── headerparameters/
│           │                       │   ├── HeaderParameterTestController.kt
│           │                       │   └── SpringConverterHeaderParameterTest.kt
│           │                       ├── httpmethod/
│           │                       │   ├── HttpMethodTestController.kt
│           │                       │   └── SpringConverterHttpMethodTest.kt
│           │                       ├── matrixparameters/
│           │                       │   ├── MatrixParameterTestController.kt
│           │                       │   └── SpringConverterMatrixParameterTest.kt
│           │                       ├── path/
│           │                       │   ├── PathTestController.kt
│           │                       │   └── SpringConverterPathTest.kt
│           │                       ├── pathparameters/
│           │                       │   ├── PathParameterTestController.kt
│           │                       │   └── SpringConverterPathParameterTest.kt
│           │                       ├── produces/
│           │                       │   ├── redirect/
│           │                       │   │   ├── RedirectTestController.kt
│           │                       │   │   └── SpringControllerRedirectTest.kt
│           │                       │   ├── responsebody/
│           │                       │   │   ├── ProducesResponseBodyAnnotationTestController.kt
│           │                       │   │   └── SpringConverterProducesResponseBodyAnnotationTest.kt
│           │                       │   ├── restcontroller/
│           │                       │   │   ├── ProducesRestControllerAnnotationTestController.kt
│           │                       │   │   └── SpringConverterProducesRestControllerAnnotationTest.kt
│           │                       │   └── servletresponse/
│           │                       │       ├── ProducesServletResponseTestController.kt
│           │                       │       └── SpringConverterProducesServletResponseTest.kt
│           │                       └── queryparameters/
│           │                           ├── QueryParameterTestController.kt
│           │                           └── SpringConverterQueryParameterTest.kt
│           └── resources/
│               └── .gitemptydir
└── wadl/
    ├── README.md
    ├── build.gradle
    └── src/
        ├── main/
        │   ├── kotlin/
        │   │   └── de/
        │   │       └── codecentric/
        │   │           └── hikaku/
        │   │               └── converters/
        │   │                   └── wadl/
        │   │                       ├── WadlConverter.kt
        │   │                       └── extensions/
        │   │                           └── NodeExtensions.kt
        │   └── resources/
        │       └── .gitemptydir
        └── test/
            ├── kotlin/
            │   └── de/
            │       └── codecentric/
            │           └── hikaku/
            │               └── converters/
            │                   └── wadl/
            │                       ├── WadlConverterConsumesTest.kt
            │                       ├── WadlConverterEndpointTest.kt
            │                       ├── WadlConverterHeaderParameterTest.kt
            │                       ├── WadlConverterInvalidInputTest.kt
            │                       ├── WadlConverterMatrixParameterTest.kt
            │                       ├── WadlConverterPathParameterTest.kt
            │                       ├── WadlConverterProducesTest.kt
            │                       └── WadlConverterQueryParameterTest.kt
            └── resources/
                ├── consumes/
                │   ├── consumes_media_types_not_taken_from_produces.wadl
                │   ├── consumes_no_media_types.wadl
                │   └── consumes_three_media_types.wadl
                ├── endpoints/
                │   ├── endpoints.wadl
                │   ├── endpoints_two_different_paths.wadl
                │   └── endpoints_two_nested_paths.wadl
                ├── header_parameters.wadl
                ├── invalid_input/
                │   ├── empty_file.wadl
                │   ├── syntax_error.wadl
                │   └── whitespaces_only_file.wadl
                ├── matrix_parameters.wadl
                ├── path_parameters.wadl
                ├── produces/
                │   ├── produces_media_types_not_taken_from_consumes.wadl
                │   ├── produces_no_media_types.wadl
                │   └── produces_three_media_types.wadl
                └── query_parameters.wadl
Condensed preview — 305 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (875K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 596,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve hikaku\ntitle: ''\nlabels: Bug\nassignees: ''\n\n---\n\n# Setup "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 426,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for hikaku\ntitle: ''\nlabels: Feature Request\nassignees: ''\n\n---\n\n**Is y"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "chars": 110,
    "preview": "---\nname: Question\nabout: Got a question about hikaku for us?\ntitle: ''\nlabels: Question\nassignees: ''\n\n---\n\n\n"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 109,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"gradle\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".gitignore",
    "chars": 4599,
    "preview": "# Custom\n\n**/out/\n\n\n# Created by https://www.gitignore.io/api/linux,macos,gradle,kotlin,windows,intellij,intellij+iml,in"
  },
  {
    "path": ".travis.yml",
    "chars": 292,
    "preview": "language: bash\nmatrix:\n  include:\n    - env: JDK=\"openjdk@1.11.0-2\"\n      os: linux\n      dist: trusty\n    - env: JDK=\"o"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 5760,
    "preview": "# hikaku\n[![Build Status](https://api.travis-ci.org/codecentric/hikaku.svg?branch=master)](https://travis-ci.org/codecen"
  },
  {
    "path": "build.gradle",
    "chars": 3725,
    "preview": "buildscript {\n    ext {\n        kotlinVersion = '1.5.21'\n        jvmVersion = '1.8'\n    }\n\n    repositories {\n        ma"
  },
  {
    "path": "core/build.gradle",
    "chars": 398,
    "preview": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-core'\n\nuploadArchives {\n  repositories {\n    mavenDeployer {\n"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/Hikaku.kt",
    "chars": 4078,
    "preview": "package de.codecentric.hikaku\n\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.conve"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/HikakuConfig.kt",
    "chars": 804,
    "preview": "package de.codecentric.hikaku\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hikaku.reporters.Co"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/SupportedFeatures.kt",
    "chars": 945,
    "preview": "package de.codecentric.hikaku\n\nimport de.codecentric.hikaku.converters.EndpointConverter\n\n/**\n * A list of features supp"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/converters/AbstractEndpointConverter.kt",
    "chars": 393,
    "preview": "package de.codecentric.hikaku.converters\n\nimport de.codecentric.hikaku.endpoints.Endpoint\n\n/**\n * Abstract [EndpointConv"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/converters/ClassLocator.kt",
    "chars": 1620,
    "preview": "package de.codecentric.hikaku.converters\n\nimport de.codecentric.hikaku.extensions.extension\nimport de.codecentric.hikaku"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/converters/EndpointConverter.kt",
    "chars": 637,
    "preview": "package de.codecentric.hikaku.converters\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.Su"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/converters/EndpointConverterException.kt",
    "chars": 322,
    "preview": "package de.codecentric.hikaku.converters\n\n/**\n * Is thrown in case an [EndpointConverter] is not able to perform the con"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/Endpoint.kt",
    "chars": 957,
    "preview": "package de.codecentric.hikaku.endpoints\n\n/**\n * A single [Endpoint] containing all information. Each [Endpoint] consists"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/HeaderParameter.kt",
    "chars": 135,
    "preview": "package de.codecentric.hikaku.endpoints\n\ndata class HeaderParameter(\n    val parameterName: String,\n    val required: Bo"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/HttpMethod.kt",
    "chars": 150,
    "preview": "package de.codecentric.hikaku.endpoints\n\nenum class HttpMethod {\n    GET,\n    POST,\n    HEAD,\n    PUT,\n    PATCH,\n    DE"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/MatrixParameter.kt",
    "chars": 143,
    "preview": "package de.codecentric.hikaku.endpoints\n\ndata class MatrixParameter(\n        val parameterName: String,\n        val requ"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/PathParameter.kt",
    "chars": 102,
    "preview": "package de.codecentric.hikaku.endpoints\n\ndata class PathParameter(\n        val parameterName: String\n)"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/endpoints/QueryParameter.kt",
    "chars": 142,
    "preview": "package de.codecentric.hikaku.endpoints\n\ndata class QueryParameter(\n        val parameterName: String,\n        val requi"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/extensions/ClassExtensions.kt",
    "chars": 369,
    "preview": "package de.codecentric.hikaku.extensions\n\nimport kotlin.reflect.KClass\nimport kotlin.reflect.jvm.jvmName\n\nfun KClass<*>."
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/extensions/FileExtensions.kt",
    "chars": 169,
    "preview": "package de.codecentric.hikaku.extensions\n\nimport java.io.File\n\nfun File.checkFileValidity(vararg extensions: String) {\n "
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/extensions/PathExtensions.kt",
    "chars": 705,
    "preview": "package de.codecentric.hikaku.extensions\n\nimport java.nio.file.Files\nimport java.nio.file.Path\n\nfun Path.nameWithoutExte"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/reporters/CommandLineReporter.kt",
    "chars": 3487,
    "preview": "package de.codecentric.hikaku.reporters\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.Sup"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/reporters/MatchResult.kt",
    "chars": 986,
    "preview": "package de.codecentric.hikaku.reporters\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hikaku.end"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/reporters/NoOperationReporter.kt",
    "chars": 192,
    "preview": "package de.codecentric.hikaku.reporters\n\n/**\n * Receives the result and does nothing.\n */\nclass NoOperationReporter : Re"
  },
  {
    "path": "core/src/main/kotlin/de/codecentric/hikaku/reporters/Reporter.kt",
    "chars": 195,
    "preview": "package de.codecentric.hikaku.reporters\n\n/**\n * A [Reporter] will receive the [MatchResult] before the test terminates.\n"
  },
  {
    "path": "core/src/main/resources/.gitemptydir",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "core/src/test/kotlin/de/codecentric/hikaku/HikakuTest.kt",
    "chars": 68676,
    "preview": "package de.codecentric.hikaku\n\nimport de.codecentric.hikaku.SupportedFeatures.Feature\nimport de.codecentric.hikaku.conve"
  },
  {
    "path": "core/src/test/kotlin/de/codecentric/hikaku/extensions/ClassExtensionsTest.kt",
    "chars": 1855,
    "preview": "package de.codecentric.hikaku.extensions\n\nimport org.assertj.core.api.Assertions.assertThat\nimport org.junit.jupiter.api"
  },
  {
    "path": "core/src/test/kotlin/de/codecentric/hikaku/extensions/FileExtensionsTest.kt",
    "chars": 1656,
    "preview": "package de.codecentric.hikaku.extensions\n\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport j"
  },
  {
    "path": "core/src/test/kotlin/de/codecentric/hikaku/extensions/PathExtensionsTest.kt",
    "chars": 1693,
    "preview": "package de.codecentric.hikaku.extensions\n\nimport org.junit.jupiter.api.Nested\nimport org.junit.jupiter.api.Test\nimport j"
  },
  {
    "path": "core/src/test/resources/test_file.txt",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/config.md",
    "chars": 549,
    "preview": "# hikaku - Config\n\nThe following is a list if configurations.\n\n| config parameter | since | default value | description "
  },
  {
    "path": "docs/features.md",
    "chars": 1873,
    "preview": "# hikaku - Features\n\nThe following table gives an overview of all features and which converter supports which feature.\nT"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 200,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
  },
  {
    "path": "gradlew",
    "chars": 5766,
    "preview": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0"
  },
  {
    "path": "gradlew.bat",
    "chars": 2763,
    "preview": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (th"
  },
  {
    "path": "install-jdk.sh",
    "chars": 1492,
    "preview": "#!/bin/bash\ninstall_jdk () {\n    if $jabba use $JDK; then\n        echo $JDK was available and Jabba is using it\n    else"
  },
  {
    "path": "jax-rs/README.md",
    "chars": 771,
    "preview": "# hikaku - JAX-RS\n\nConverter for JAX-RS. This converter can be used with frameworks that make use of JAX-RS. For instanc"
  },
  {
    "path": "jax-rs/build.gradle",
    "chars": 447,
    "preview": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-jax-rs'\n\ndependencies {\n  api project(':core')\n  api 'jakarta"
  },
  {
    "path": "jax-rs/src/main/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverter.kt",
    "chars": 7816,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hik"
  },
  {
    "path": "jax-rs/src/main/resources/.gitemptydir",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterConsumesTest.kt",
    "chars": 4770,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hi"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterDeprecationTest.kt",
    "chars": 1706,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hi"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterHeaderParametersTest.kt",
    "chars": 925,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hi"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterHttpMethodsTest.kt",
    "chars": 1131,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hi"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterMatrixParametersTest.kt",
    "chars": 918,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hi"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterPackageDefinitionTest.kt",
    "chars": 667,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimpor"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterPathParametersTest.kt",
    "chars": 1273,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hi"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterPathTests.kt",
    "chars": 1973,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hi"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterProducesTest.kt",
    "chars": 4341,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hi"
  },
  {
    "path": "jax-rs/src/test/kotlin/de/codecentric/hikaku/converters/jaxrs/JaxRsConverterQueryParameterTest.kt",
    "chars": 914,
    "preview": "package de.codecentric.hikaku.converters.jaxrs\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hi"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/functiondeclarationoverwritesclassdeclaration/FunctionDeclarationOverwritesClassDeclaration.kt",
    "chars": 422,
    "preview": "package test.jaxrs.consumes.functiondeclarationoverwritesclassdeclaration\n\nimport jakarta.ws.rs.Consumes\nimport jakarta."
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/multiplemediatypesonclass/MultipleMediaTypesOnClass.kt",
    "chars": 353,
    "preview": "package test.jaxrs.consumes.multiplemediatypesonclass\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport jak"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/multiplemediatypesonfunction/MultipleMediaTypesOnFunction.kt",
    "chars": 364,
    "preview": "package test.jaxrs.consumes.multiplemediatypesonfunction\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport "
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/noannotation/NoAnnotation.kt",
    "chars": 249,
    "preview": "package test.jaxrs.consumes.noannotation\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\ndata class Todo(val descri"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypeonclass/ProducesOnClass.kt",
    "chars": 322,
    "preview": "package test.jaxrs.consumes.singlemediatypeonclass\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport jakart"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypeonfunction/ProducesOnFunction.kt",
    "chars": 332,
    "preview": "package test.jaxrs.consumes.singlemediatypeonfunction\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nimport jak"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypewithoutrequestbody/SingleMediaTypeWithoutRequestBody.kt",
    "chars": 268,
    "preview": "package test.jaxrs.consumes.singlemediatypewithoutrequestbody\n\nimport jakarta.ws.rs.Consumes\nimport jakarta.ws.rs.GET\nim"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/consumes/singlemediatypewithoutrequestbodybutotherannotatedparameter/SingleMediaTypeWithoutRequestBodyButOtherAnnotatedParameter.kt",
    "chars": 315,
    "preview": "package test.jaxrs.consumes.singlemediatypewithoutrequestbodybutotherannotatedparameter\n\nimport jakarta.ws.rs.*\n\n@Path(\""
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/deprecation/none/NoDeprecation.kt",
    "chars": 158,
    "preview": "package test.jaxrs.deprecation.none\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\nclass NoDepreca"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/deprecation/onclass/DeprecationOnClass.kt",
    "chars": 186,
    "preview": "package test.jaxrs.deprecation.onclass\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\n@Deprecated("
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/deprecation/onfunction/DeprecationOnFunction.kt",
    "chars": 196,
    "preview": "package test.jaxrs.deprecation.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\nclass Dep"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/headerparameters/onfunction/HeaderParametersOnFunction.kt",
    "chars": 290,
    "preview": "package test.jaxrs.headerparameters.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.HeaderParam\nimport jakarta"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/httpmethod/allmethods/AllHttpMethods.kt",
    "chars": 357,
    "preview": "package test.jaxrs.httpmethod.allmethods\n\nimport jakarta.ws.rs.*\n\n@Path(\"/todos\")\nclass AllHttpMethods {\n\n    @GET\n    f"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/httpmethod/noannotation/NoAnnotation.kt",
    "chars": 100,
    "preview": "package test.jaxrs.httpmethod.noannotation\n\nimport jakarta.ws.rs.Path\n\n@Path(\"\")\nclass NoAnnotation\n"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/matrixparameters/onfunction/MatrixParametersOnFunction.kt",
    "chars": 275,
    "preview": "package test.jaxrs.matrixparameters.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.MatrixParam\nimport jakarta"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/nestedpath/NestedPath.kt",
    "chars": 172,
    "preview": "package test.jaxrs.path.nestedpath\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todo\")\nclass NestedPath "
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/nestedpathwithoutleadingslash/NestedPathWithoutLeadingSlash.kt",
    "chars": 190,
    "preview": "package test.jaxrs.path.nestedpathwithoutleadingslash\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todo\""
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/nopathonclass/NoPathAnnotationOnclass.kt",
    "chars": 174,
    "preview": "package test.jaxrs.path.nopathonclass\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\nclass NoPathAnnotationOnclass"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/simplepath/SimplePath.kt",
    "chars": 154,
    "preview": "package test.jaxrs.path.simplepath\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\nclass SimplePath"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/path/simplepathwithoutleadingslash/SimplePathWithoutLeadingSlash.kt",
    "chars": 191,
    "preview": "package test.jaxrs.path.simplepathwithoutleadingslash\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"todos\""
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/pathparameters/nopathparameter/NoPathParameter.kt",
    "chars": 193,
    "preview": "package test.jaxrs.pathparameters.nopathparameter\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\n@Path(\"/todos\")\nc"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/pathparameters/onfunction/PathParameterOnFunction.kt",
    "chars": 284,
    "preview": "package test.jaxrs.pathparameters.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.Pa"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/functiondeclarationoverwritesclassdeclaration/FunctionDeclarationOverwritesClassDeclaration.kt",
    "chars": 387,
    "preview": "package test.jaxrs.produces.functiondeclarationoverwritesclassdeclaration\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/multiplemediatypesonclass/MultipleMediaTypesOnClass.kt",
    "chars": 319,
    "preview": "package test.jaxrs.produces.multiplemediatypesonclass\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/multiplemediatypesonfunction/MultipleMediaTypesOnFunction.kt",
    "chars": 329,
    "preview": "package test.jaxrs.produces.multiplemediatypesonfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jaka"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/noannotation/NoAnnotation.kt",
    "chars": 214,
    "preview": "package test.jaxrs.produces.noannotation\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\n\ndata class Todo(val descri"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/singlemediatypeonclass/ProducesOnClass.kt",
    "chars": 287,
    "preview": "package test.jaxrs.produces.singlemediatypeonclass\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/singlemediatypeonfunction/ProducesOnFunction.kt",
    "chars": 297,
    "preview": "package test.jaxrs.produces.singlemediatypeonfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta"
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/produces/singlemediatypewithoutreturntype/SingleMediaTypeWithoutReturnType.kt",
    "chars": 266,
    "preview": "package test.jaxrs.produces.singlemediatypewithoutreturntype\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport "
  },
  {
    "path": "jax-rs/src/test/kotlin/test/jaxrs/queryparameters/onfunction/QueryParameterOnFunction.kt",
    "chars": 277,
    "preview": "package test.jaxrs.queryparameters.onfunction\n\nimport jakarta.ws.rs.GET\nimport jakarta.ws.rs.Path\nimport jakarta.ws.rs.Q"
  },
  {
    "path": "jax-rs/src/test/resources/.gitemptydir",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "micronaut/README.md",
    "chars": 3055,
    "preview": "# hikaku - Micronaut\n\nConverter for Micronaut.\n\n## Feature Support\n\nPlease refer to the list of [all features](../docs/f"
  },
  {
    "path": "micronaut/build.gradle",
    "chars": 452,
    "preview": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-micronaut'\n\ndependencies {\n  api project(':core')\n  api 'io.m"
  },
  {
    "path": "micronaut/src/main/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverter.kt",
    "chars": 10125,
    "preview": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric"
  },
  {
    "path": "micronaut/src/main/resources/.gitemptydir",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterConsumesTest.kt",
    "chars": 6723,
    "preview": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentri"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterDeprecationTest.kt",
    "chars": 1738,
    "preview": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentri"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterHeaderParameterTest.kt",
    "chars": 1544,
    "preview": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentri"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterPackageDefinitionTest.kt",
    "chars": 683,
    "preview": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\ni"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterPathParameterTest.kt",
    "chars": 2170,
    "preview": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentri"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterPathTest.kt",
    "chars": 7848,
    "preview": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentri"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterProducesTest.kt",
    "chars": 6718,
    "preview": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentri"
  },
  {
    "path": "micronaut/src/test/kotlin/de/codecentric/hikaku/converters/micronaut/MicronautConverterQueryParameterTest.kt",
    "chars": 2246,
    "preview": "package de.codecentric.hikaku.converters.micronaut\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentri"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/Todo.kt",
    "chars": 69,
    "preview": "package test.micronaut\n\ndata class Todo(val description: String = \"\")"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/default/ConsumesDefaultMediaTypeTestController.kt",
    "chars": 346,
    "preview": "package test.micronaut.consumes.default\n\nimport io.micronaut.http.annotation.Body\nimport io.micronaut.http.annotation.Co"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onclass/consumesoverridescontroller/multiplemediatypes/ConsumesMultipleMediaTypesTestController.kt",
    "chars": 535,
    "preview": "package test.micronaut.consumes.onclass.consumesoverridescontroller.multiplemediatypes\n\nimport io.micronaut.http.annotat"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onclass/consumesoverridescontroller/singlemediatype/ConsumesSingleMediaTypeTestController.kt",
    "chars": 491,
    "preview": "package test.micronaut.consumes.onclass.consumesoverridescontroller.singlemediatype\n\nimport io.micronaut.http.annotation"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onclass/onlycontroller/multiplemediatypes/ConsumesMultipleMediaTypesTestController.kt",
    "chars": 428,
    "preview": "package test.micronaut.consumes.onclass.onlycontroller.multiplemediatypes\n\nimport io.micronaut.http.annotation.Body\nimpo"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onclass/onlycontroller/singlemediatype/ConsumesSingleMediaTypeTestController.kt",
    "chars": 404,
    "preview": "package test.micronaut.consumes.onclass.onlycontroller.singlemediatype\n\nimport io.micronaut.http.annotation.Body\nimport "
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onfunction/consumesoverridescontroller/multiplemediatypes/ConsumesMultipleMediaTypesTestController.kt",
    "chars": 542,
    "preview": "package test.micronaut.consumes.onfunction.consumesoverridescontroller.multiplemediatypes\n\nimport io.micronaut.http.anno"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onfunction/consumesoverridescontroller/singlemediatype/ConsumesSingleMediaTypeTestController.kt",
    "chars": 498,
    "preview": "package test.micronaut.consumes.onfunction.consumesoverridescontroller.singlemediatype\n\nimport io.micronaut.http.annotat"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onfunction/onlyconsumes/multiplemediatypes/ConsumesMultipleMediaTypesTestController.kt",
    "chars": 429,
    "preview": "package test.micronaut.consumes.onfunction.onlyconsumes.multiplemediatypes\n\nimport io.micronaut.http.annotation.Body\nimp"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/consumes/onfunction/onlyconsumes/singlemediatype/ConsumesSingleMediaTypeTestController.kt",
    "chars": 405,
    "preview": "package test.micronaut.consumes.onfunction.onlyconsumes.singlemediatype\n\nimport io.micronaut.http.annotation.Body\nimport"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/deprecation/none/NoDeprecation.kt",
    "chars": 203,
    "preview": "package test.micronaut.deprecation.none\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotat"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/deprecation/onclass/DeprecationOnClass.kt",
    "chars": 231,
    "preview": "package test.micronaut.deprecation.onclass\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.anno"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/deprecation/onfunction/DeprecationOnFunction.kt",
    "chars": 241,
    "preview": "package test.micronaut.deprecation.onfunction\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.a"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/headerparameters/optional/HeaderParameterTestController.kt",
    "chars": 366,
    "preview": "package test.micronaut.headerparameters.optional\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.htt"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/headerparameters/required/HeaderParameterTestController.kt",
    "chars": 343,
    "preview": "package test.micronaut.headerparameters.required\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.htt"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/delete/CombinedControllerAnnotationWithDeletePathTestController.kt",
    "chars": 298,
    "preview": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.delete\n\nimport io.micronaut.http.annotation.Contro"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/get/CombinedControllerAnnotationWithGetPathTestController.kt",
    "chars": 286,
    "preview": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.get\n\nimport io.micronaut.http.annotation.Controlle"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/head/CombinedControllerAnnotationWithHeadPathTestController.kt",
    "chars": 290,
    "preview": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.head\n\nimport io.micronaut.http.annotation.Controll"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/options/CombinedControllerAnnotationWithOptionsPathTestController.kt",
    "chars": 302,
    "preview": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.options\n\nimport io.micronaut.http.annotation.Contr"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/patch/CombinedControllerAnnotationWithPatchPathTestController.kt",
    "chars": 294,
    "preview": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.patch\n\nimport io.micronaut.http.annotation.Control"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/post/CombinedControllerAnnotationWithPostPathTestController.kt",
    "chars": 290,
    "preview": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.post\n\nimport io.micronaut.http.annotation.Controll"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/combinedcontrollerandhttpmethodannotation/put/CombinedControllerAnnotationWithPutPathTestController.kt",
    "chars": 286,
    "preview": "package test.micronaut.path.combinedcontrollerandhttpmethodannotation.put\n\nimport io.micronaut.http.annotation.Controlle"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/firstpathsegmentwithoutleadingslash/FirstPathSegmentWithoutLeadingSlashTestController.kt",
    "chars": 271,
    "preview": "package test.micronaut.path.firstpathsegmentwithoutleadingslash\n\nimport io.micronaut.http.annotation.Controller\nimport i"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/innerpathsegmentwithoutleadingslash/InnerPathSegmentWithoutLeadingSlashTestController.kt",
    "chars": 271,
    "preview": "package test.micronaut.path.innerpathsegmentwithoutleadingslash\n\nimport io.micronaut.http.annotation.Controller\nimport i"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/nohttpmethodannotation/NoHttpMethodAnnotationTestController.kt",
    "chars": 189,
    "preview": "package test.micronaut.path.nohttpmethodannotation\n\nimport io.micronaut.http.annotation.Controller\n\n@Controller(\"/todos\""
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/delete/OnlyControllerAnnotationWithDeletePathTestController.kt",
    "chars": 269,
    "preview": "package test.micronaut.path.onlycontrollerannotation.delete\n\nimport io.micronaut.http.annotation.Controller\nimport io.mi"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/get/OnlyControllerAnnotationWithGetPathTestController.kt",
    "chars": 257,
    "preview": "package test.micronaut.path.onlycontrollerannotation.get\n\nimport io.micronaut.http.annotation.Controller\nimport io.micro"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/head/OnlyControllerAnnotationWithHeadPathTestController.kt",
    "chars": 261,
    "preview": "package test.micronaut.path.onlycontrollerannotation.head\n\nimport io.micronaut.http.annotation.Controller\nimport io.micr"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/options/OnlyControllerAnnotationWithOptionsPathTestController.kt",
    "chars": 273,
    "preview": "package test.micronaut.path.onlycontrollerannotation.options\n\nimport io.micronaut.http.annotation.Controller\nimport io.m"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/patch/OnlyControllerAnnotationWithPatchPathTestController.kt",
    "chars": 265,
    "preview": "package test.micronaut.path.onlycontrollerannotation.patch\n\nimport io.micronaut.http.annotation.Controller\nimport io.mic"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/post/OnlyControllerAnnotationWithPostPathTestController.kt",
    "chars": 261,
    "preview": "package test.micronaut.path.onlycontrollerannotation.post\n\nimport io.micronaut.http.annotation.Controller\nimport io.micr"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/path/onlycontrollerannotation/put/OnlyControllerAnnotationWithPutPathTestController.kt",
    "chars": 257,
    "preview": "package test.micronaut.path.onlycontrollerannotation.put\n\nimport io.micronaut.http.annotation.Controller\nimport io.micro"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/pathparameters/annotation/name/PathParameterDefinedByAnnotationTestController.kt",
    "chars": 380,
    "preview": "package test.micronaut.pathparameters.annotation.name\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronau"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/pathparameters/annotation/value/PathParameterDefinedByAnnotationTestController.kt",
    "chars": 374,
    "preview": "package test.micronaut.pathparameters.annotation.value\n\nimport io.micronaut.http.annotation.Controller\nimport io.microna"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/pathparameters/variable/PathParameterDefinedByVariableNameTestController.kt",
    "chars": 292,
    "preview": "package test.micronaut.pathparameters.variable\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http."
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/default/DefaultTestController.kt",
    "chars": 261,
    "preview": "package test.micronaut.produces.default\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http.annotat"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onclass/onlycontroller/multiplemediatypes/ProducesMultipleMediaTypesTestController.kt",
    "chars": 343,
    "preview": "package test.micronaut.produces.onclass.onlycontroller.multiplemediatypes\n\nimport io.micronaut.http.annotation.Controlle"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onclass/onlycontroller/singlemediatype/ProducesSingleMediaTypeTestController.kt",
    "chars": 319,
    "preview": "package test.micronaut.produces.onclass.onlycontroller.singlemediatype\n\nimport io.micronaut.http.annotation.Controller\ni"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onclass/producesoverridescontroller/multiplemediatypes/ProducesMultipleMediaTypesTestController.kt",
    "chars": 450,
    "preview": "package test.micronaut.produces.onclass.producesoverridescontroller.multiplemediatypes\n\nimport io.micronaut.http.annotat"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onclass/producesoverridescontroller/singlemediatype/ProducesSingleMediaTypeTestController.kt",
    "chars": 406,
    "preview": "package test.micronaut.produces.onclass.producesoverridescontroller.singlemediatype\n\nimport io.micronaut.http.annotation"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onfunction/onlyproduces/multiplemediatypes/ProducesMultipleMediaTypesTestController.kt",
    "chars": 390,
    "preview": "package test.micronaut.produces.onfunction.onlyproduces.multiplemediatypes\n\nimport io.micronaut.http.annotation.Controll"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onfunction/onlyproduces/singlemediatype/ProducesSingleMediaTypeTestController.kt",
    "chars": 365,
    "preview": "package test.micronaut.produces.onfunction.onlyproduces.singlemediatype\n\nimport io.micronaut.http.annotation.Controller\n"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onfunction/producesoverridescontroller/multiplemediatypes/ProducesMultipleMediaTypesTestController.kt",
    "chars": 457,
    "preview": "package test.micronaut.produces.onfunction.producesoverridescontroller.multiplemediatypes\n\nimport io.micronaut.http.anno"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/produces/onfunction/producesoverridescontroller/singlemediatype/ProducesSingleMediaTypeTestController.kt",
    "chars": 413,
    "preview": "package test.micronaut.produces.onfunction.producesoverridescontroller.singlemediatype\n\nimport io.micronaut.http.annotat"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/queryparameters/optional/QueryParameterTestController.kt",
    "chars": 363,
    "preview": "package test.micronaut.queryparameters.optional\n\nimport io.micronaut.http.annotation.Controller\nimport io.micronaut.http"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/queryparameters/required/annotation/QueryParameterTestController.kt",
    "chars": 352,
    "preview": "package test.micronaut.queryparameters.required.annotation\n\nimport io.micronaut.http.annotation.Controller\nimport io.mic"
  },
  {
    "path": "micronaut/src/test/kotlin/test/micronaut/queryparameters/required/withoutannotation/QueryParameterTestController.kt",
    "chars": 290,
    "preview": "package test.micronaut.queryparameters.required.withoutannotation\n\nimport io.micronaut.http.annotation.Controller\nimport"
  },
  {
    "path": "micronaut/src/test/resources/resources/.gitemptydir",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "openapi/README.md",
    "chars": 326,
    "preview": "# hikaku - OpenAPI\n\nSupports OpenAPI 3.0.X\n\n## Feature Support\n\nPlease refer to the list of [all features](../docs/featu"
  },
  {
    "path": "openapi/build.gradle",
    "chars": 457,
    "preview": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-openapi'\n\ndependencies {\n  api project(':core')\n  api 'io.swa"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverter.kt",
    "chars": 4211,
    "preview": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.h"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extensions/PathItemExtensions.kt",
    "chars": 924,
    "preview": "package de.codecentric.hikaku.converters.openapi.extensions\n\nimport io.swagger.v3.oas.models.Operation\nimport io.swagger"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extensions/ReferencedSchema.kt",
    "chars": 407,
    "preview": "package de.codecentric.hikaku.converters.openapi.extensions\n\nimport io.swagger.v3.oas.models.parameters.Parameter\nimport"
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/ConsumesExtractor.kt",
    "chars": 1212,
    "preview": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions."
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/HeaderParameterExtractor.kt",
    "chars": 1775,
    "preview": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions."
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/PathParameterExtractor.kt",
    "chars": 1709,
    "preview": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions."
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/ProducesExtractor.kt",
    "chars": 1432,
    "preview": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions."
  },
  {
    "path": "openapi/src/main/kotlin/de/codecentric/hikaku/converters/openapi/extractors/QueryParameterExtractor.kt",
    "chars": 1760,
    "preview": "package de.codecentric.hikaku.converters.openapi.extractors\n\nimport de.codecentric.hikaku.converters.openapi.extensions."
  },
  {
    "path": "openapi/src/main/resources/.gitemptydir",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterConsumesTest.kt",
    "chars": 1542,
    "preview": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric."
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterDeprecationTest.kt",
    "chars": 1599,
    "preview": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric."
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterEndpointTest.kt",
    "chars": 2113,
    "preview": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric."
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterHeaderParameterTest.kt",
    "chars": 2764,
    "preview": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport org.asse"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterInvalidInputTest.kt",
    "chars": 2741,
    "preview": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimp"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterPathParameterTest.kt",
    "chars": 2751,
    "preview": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport org.assert"
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterProducesTest.kt",
    "chars": 2690,
    "preview": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric."
  },
  {
    "path": "openapi/src/test/kotlin/de/codecentric/hikaku/converters/openapi/OpenApiConverterQueryParameterTest.kt",
    "chars": 2670,
    "preview": "package de.codecentric.hikaku.converters.openapi\n\nimport de.codecentric.hikaku.endpoints.QueryParameter\nimport org.asser"
  },
  {
    "path": "openapi/src/test/resources/consumes/consumes_inline.yaml",
    "chars": 381,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    post:\n      description: ''\n      requestB"
  },
  {
    "path": "openapi/src/test/resources/consumes/consumes_requestbody_in_components.yaml",
    "chars": 594,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    post:\n      description: ''\n      requestB"
  },
  {
    "path": "openapi/src/test/resources/deprecation/deprecation_none.yaml",
    "chars": 339,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      deprecated: false\n      descrip"
  },
  {
    "path": "openapi/src/test/resources/deprecation/deprecation_operation.yaml",
    "chars": 338,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      deprecated: true\n      descript"
  },
  {
    "path": "openapi/src/test/resources/endpoints/endpoints_all_http_methods.yaml",
    "chars": 798,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses"
  },
  {
    "path": "openapi/src/test/resources/endpoints/endpoints_two_different_paths.yaml",
    "chars": 260,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses"
  },
  {
    "path": "openapi/src/test/resources/endpoints/endpoints_two_nested_paths.yaml",
    "chars": 267,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses"
  },
  {
    "path": "openapi/src/test/resources/header_parameter/common_header_parameter_in_components.yaml",
    "chars": 594,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    parameters:\n      - name: x-b3-traceid\n   "
  },
  {
    "path": "openapi/src/test/resources/header_parameter/common_header_parameter_inline.yaml",
    "chars": 503,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    parameters:\n      - name: x-b3-traceid\n   "
  },
  {
    "path": "openapi/src/test/resources/header_parameter/header_parameter_in_components.yaml",
    "chars": 610,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: 'Get all todos'\n  "
  },
  {
    "path": "openapi/src/test/resources/header_parameter/header_parameter_inline.yaml",
    "chars": 529,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: 'Get all todos'\n  "
  },
  {
    "path": "openapi/src/test/resources/invalid_input/empty_file.yaml",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "openapi/src/test/resources/invalid_input/syntax_error.yaml",
    "chars": 191,
    "preview": "openapi: 3.0.2\ninfo:\n  title: Todo List\npaths:\n  todos\n    get\n      summary: Add a new todo\n      description: 'Creates"
  },
  {
    "path": "openapi/src/test/resources/invalid_input/whitespaces_only_file.yaml",
    "chars": 35,
    "preview": "                                   "
  },
  {
    "path": "openapi/src/test/resources/path_parameter/common_path_parameter_in_components.yaml",
    "chars": 678,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/{id}:\n    parameters:\n      - $ref: \"#/componen"
  },
  {
    "path": "openapi/src/test/resources/path_parameter/common_path_parameter_inline.yaml",
    "chars": 597,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/{id}:\n    parameters:\n      - name: id\n        "
  },
  {
    "path": "openapi/src/test/resources/path_parameter/path_parameter_in_components.yaml",
    "chars": 967,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/{id}:\n    get:\n      description: 'Get all todo"
  },
  {
    "path": "openapi/src/test/resources/path_parameter/path_parameter_inline.yaml",
    "chars": 1039,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/{id}:\n    get:\n      description: 'Get all todo"
  },
  {
    "path": "openapi/src/test/resources/produces/produces_inline.yaml",
    "chars": 368,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses"
  },
  {
    "path": "openapi/src/test/resources/produces/produces_no_content_type.yaml",
    "chars": 181,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    delete:\n      description: 'Delete all tod"
  },
  {
    "path": "openapi/src/test/resources/produces/produces_response_in_components.yaml",
    "chars": 544,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: ''\n      responses"
  },
  {
    "path": "openapi/src/test/resources/produces/produces_with_default.yaml",
    "chars": 815,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos/query:\n    get:\n      description: ''\n      res"
  },
  {
    "path": "openapi/src/test/resources/query_parameter/common_query_parameter_in_components.yaml",
    "chars": 604,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    parameters:\n      - $ref: \"#/components/pa"
  },
  {
    "path": "openapi/src/test/resources/query_parameter/common_query_parameter_inline.yaml",
    "chars": 525,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    parameters:\n      - name: limit\n        in"
  },
  {
    "path": "openapi/src/test/resources/query_parameter/query_parameter_in_components.yaml",
    "chars": 590,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: 'Get all todos'\n  "
  },
  {
    "path": "openapi/src/test/resources/query_parameter/query_parameter_inline.yaml",
    "chars": 523,
    "preview": "openapi: 3.0.2\ninfo:\n  version: 1.0.0\n  title: Todo List\npaths:\n  /todos:\n    get:\n      description: 'Get all todos'\n  "
  },
  {
    "path": "raml/README.md",
    "chars": 429,
    "preview": "# hikaku - RAML\n\nSupports RAML 1.X\n\n## Feature Support\n\nPlease refer to the list of [all features](../docs/features.md)."
  },
  {
    "path": "raml/build.gradle",
    "chars": 476,
    "preview": "group = 'de.codecentric.hikaku'\narchivesBaseName = 'hikaku-raml'\n\ndependencies {\n  api project(':core')\n  api 'org.raml:"
  },
  {
    "path": "raml/src/main/kotlin/de/codecentric/hikaku/converters/raml/RamlConverter.kt",
    "chars": 2949,
    "preview": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.SupportedFeatures\nimport de.codecentric.hika"
  },
  {
    "path": "raml/src/main/kotlin/de/codecentric/hikaku/converters/raml/extensions/MethodExtensions.kt",
    "chars": 1316,
    "preview": "package de.codecentric.hikaku.converters.raml.extensions\n\nimport de.codecentric.hikaku.endpoints.HeaderParameter\nimport "
  },
  {
    "path": "raml/src/main/kotlin/de/codecentric/hikaku/converters/raml/extensions/ResourceExtensions.kt",
    "chars": 350,
    "preview": "package de.codecentric.hikaku.converters.raml.extensions\n\nimport de.codecentric.hikaku.endpoints.PathParameter\nimport or"
  },
  {
    "path": "raml/src/main/resources/.gitemptydir",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterConsumesTest.kt",
    "chars": 4179,
    "preview": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.converters.EndpointConverterException\nimport"
  },
  {
    "path": "raml/src/test/kotlin/de/codecentric/hikaku/converters/raml/RamlConverterDeprecationTest.kt",
    "chars": 2184,
    "preview": "package de.codecentric.hikaku.converters.raml\n\nimport de.codecentric.hikaku.endpoints.Endpoint\nimport de.codecentric.hik"
  }
]

// ... and 105 more files (download for full content)

About this extraction

This page contains the full source code of the codecentric/hikaku GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 305 files (793.0 KB), approximately 158.9k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!