Repository: swagger-api/swagger-core Branch: master Commit: 1d25dc1f9388 Files: 1211 Total size: 4.1 MB Directory structure: gitextract_wy3hqqbl/ ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── 01_bug_report.md │ │ ├── 02_question.md │ │ └── 03_feature_request.md │ ├── dependabot.yml │ ├── pull_request_template.md │ ├── topissuebot.yml │ └── workflows/ │ ├── codeql-analysis.yml │ ├── dependency-review.yml │ ├── maven-pulls.yml │ ├── maven-v1-pulls.yml │ ├── maven-v1.yml │ ├── maven.yml │ ├── prepare-release.yml │ └── release.yml ├── .gitignore ├── .mvn/ │ └── wrapper/ │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .whitesource ├── CI/ │ ├── CI.md │ ├── ghApiClient.py │ ├── lastRelease.py │ ├── post-release.sh │ ├── pre-release.sh │ ├── prepare-javadocs.sh │ ├── prepare-release.sh │ ├── publish-javadocs.sh │ ├── publishRelease.py │ ├── releaseNotes.py │ ├── test.py │ ├── update-v1-readme.sh │ └── update-wiki.sh ├── LICENSE ├── NOTICE ├── README.md ├── modules/ │ ├── swagger-annotations/ │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── io/ │ │ └── swagger/ │ │ └── v3/ │ │ └── oas/ │ │ └── annotations/ │ │ ├── ExternalDocumentation.java │ │ ├── Hidden.java │ │ ├── OpenAPI31.java │ │ ├── OpenAPIDefinition.java │ │ ├── Operation.java │ │ ├── Parameter.java │ │ ├── Parameters.java │ │ ├── StringToClassMapItem.java │ │ ├── Webhook.java │ │ ├── Webhooks.java │ │ ├── callbacks/ │ │ │ ├── Callback.java │ │ │ └── Callbacks.java │ │ ├── enums/ │ │ │ ├── Explode.java │ │ │ ├── ParameterIn.java │ │ │ ├── ParameterStyle.java │ │ │ ├── SecuritySchemeIn.java │ │ │ └── SecuritySchemeType.java │ │ ├── extensions/ │ │ │ ├── Extension.java │ │ │ ├── ExtensionProperty.java │ │ │ └── Extensions.java │ │ ├── headers/ │ │ │ └── Header.java │ │ ├── info/ │ │ │ ├── Contact.java │ │ │ ├── Info.java │ │ │ └── License.java │ │ ├── links/ │ │ │ ├── Link.java │ │ │ └── LinkParameter.java │ │ ├── media/ │ │ │ ├── ArraySchema.java │ │ │ ├── Content.java │ │ │ ├── DependentRequired.java │ │ │ ├── DependentRequiredMap.java │ │ │ ├── DependentSchema.java │ │ │ ├── DependentSchemas.java │ │ │ ├── DiscriminatorMapping.java │ │ │ ├── Encoding.java │ │ │ ├── ExampleObject.java │ │ │ ├── PatternProperties.java │ │ │ ├── PatternProperty.java │ │ │ ├── Schema.java │ │ │ ├── SchemaProperties.java │ │ │ └── SchemaProperty.java │ │ ├── parameters/ │ │ │ ├── RequestBody.java │ │ │ └── ValidatedParameter.java │ │ ├── responses/ │ │ │ ├── ApiResponse.java │ │ │ ├── ApiResponses.java │ │ │ └── FailedApiResponse.java │ │ ├── security/ │ │ │ ├── OAuthFlow.java │ │ │ ├── OAuthFlows.java │ │ │ ├── OAuthScope.java │ │ │ ├── SecurityRequirement.java │ │ │ ├── SecurityRequirementEntry.java │ │ │ ├── SecurityRequirements.java │ │ │ ├── SecurityScheme.java │ │ │ └── SecuritySchemes.java │ │ ├── servers/ │ │ │ ├── Server.java │ │ │ ├── ServerVariable.java │ │ │ └── Servers.java │ │ └── tags/ │ │ ├── Tag.java │ │ └── Tags.java │ ├── swagger-core/ │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── io/ │ │ │ └── swagger/ │ │ │ └── v3/ │ │ │ └── core/ │ │ │ ├── converter/ │ │ │ │ ├── AnnotatedType.java │ │ │ │ ├── ModelConverter.java │ │ │ │ ├── ModelConverterContext.java │ │ │ │ ├── ModelConverterContextImpl.java │ │ │ │ ├── ModelConverters.java │ │ │ │ └── ResolvedSchema.java │ │ │ ├── filter/ │ │ │ │ ├── AbstractSpecFilter.java │ │ │ │ ├── OpenAPI31SpecFilter.java │ │ │ │ ├── OpenAPISpecFilter.java │ │ │ │ └── SpecFilter.java │ │ │ ├── jackson/ │ │ │ │ ├── AbstractModelConverter.java │ │ │ │ ├── ApiResponsesSerializer.java │ │ │ │ ├── CallbackSerializer.java │ │ │ │ ├── ExampleSerializer.java │ │ │ │ ├── JAXBAnnotationsHelper.java │ │ │ │ ├── MediaTypeSerializer.java │ │ │ │ ├── ModelResolver.java │ │ │ │ ├── PackageVersion.java │ │ │ │ ├── PathsSerializer.java │ │ │ │ ├── Schema31Serializer.java │ │ │ │ ├── SchemaSerializer.java │ │ │ │ ├── SwaggerAnnotationIntrospector.java │ │ │ │ ├── SwaggerModule.java │ │ │ │ ├── TypeNameResolver.java │ │ │ │ └── mixin/ │ │ │ │ ├── Components31Mixin.java │ │ │ │ ├── ComponentsMixin.java │ │ │ │ ├── DateSchemaMixin.java │ │ │ │ ├── Discriminator31Mixin.java │ │ │ │ ├── DiscriminatorMixin.java │ │ │ │ ├── ExampleMixin.java │ │ │ │ ├── ExtensionsMixin.java │ │ │ │ ├── Info31Mixin.java │ │ │ │ ├── InfoMixin.java │ │ │ │ ├── LicenseMixin.java │ │ │ │ ├── MediaTypeMixin.java │ │ │ │ ├── OpenAPI31Mixin.java │ │ │ │ ├── OpenAPIMixin.java │ │ │ │ ├── OperationMixin.java │ │ │ │ ├── Schema31Mixin.java │ │ │ │ ├── SchemaConverterMixin.java │ │ │ │ └── SchemaMixin.java │ │ │ ├── model/ │ │ │ │ └── ApiDescription.java │ │ │ └── util/ │ │ │ ├── AnnotationsUtils.java │ │ │ ├── ApiResponses31Deserializer.java │ │ │ ├── ApiResponsesDeserializer.java │ │ │ ├── Callback31Deserializer.java │ │ │ ├── CallbackDeserializer.java │ │ │ ├── Configuration.java │ │ │ ├── Constants.java │ │ │ ├── DeserializationModule.java │ │ │ ├── DeserializationModule31.java │ │ │ ├── EncodingPropertyStyleEnumDeserializer.java │ │ │ ├── EncodingStyleEnumDeserializer.java │ │ │ ├── HeaderStyleEnumDeserializer.java │ │ │ ├── Json.java │ │ │ ├── Json31.java │ │ │ ├── KotlinDetector.java │ │ │ ├── Model31Deserializer.java │ │ │ ├── ModelDeserializer.java │ │ │ ├── ObjectMapperFactory.java │ │ │ ├── OpenAPI30To31.java │ │ │ ├── OpenAPI31Deserializer.java │ │ │ ├── OpenAPISchema2JsonSchema.java │ │ │ ├── Parameter31Deserializer.java │ │ │ ├── ParameterDeserializer.java │ │ │ ├── ParameterProcessor.java │ │ │ ├── PathUtils.java │ │ │ ├── Paths31Deserializer.java │ │ │ ├── PathsDeserializer.java │ │ │ ├── PrettyPrintHelper.java │ │ │ ├── PrimitiveType.java │ │ │ ├── RefUtils.java │ │ │ ├── ReferenceTypeUtils.java │ │ │ ├── ReflectionUtils.java │ │ │ ├── SchemaTypeUtils.java │ │ │ ├── SecurityScheme31Deserializer.java │ │ │ ├── SecuritySchemeDeserializer.java │ │ │ ├── SiblingAnnotationFilter.java │ │ │ ├── ValidationAnnotationsUtils.java │ │ │ ├── ValidatorProcessor.java │ │ │ ├── Yaml.java │ │ │ └── Yaml31.java │ │ └── test/ │ │ ├── java/ │ │ │ └── io/ │ │ │ └── swagger/ │ │ │ └── v3/ │ │ │ └── core/ │ │ │ ├── converting/ │ │ │ │ ├── AnnotatedTypeCachingTest.java │ │ │ │ ├── AnnotatedTypeTest.java │ │ │ │ ├── ArrayOfSubclassTest.java │ │ │ │ ├── ByteConverterTest.java │ │ │ │ ├── CompositionTest.java │ │ │ │ ├── CovariantGetterTest.java │ │ │ │ ├── EnumPropertyTest.java │ │ │ │ ├── GuavaTest.java │ │ │ │ ├── Issue5055Test.java │ │ │ │ ├── ModelConverterTest.java │ │ │ │ ├── ModelPropertyTest.java │ │ │ │ ├── NumericFormatTest.java │ │ │ │ ├── PojoTest.java │ │ │ │ ├── PolymorphicSubtypePropertyBleedTest.java │ │ │ │ ├── SwaggerSerializerTest.java │ │ │ │ └── override/ │ │ │ │ ├── CustomAnnotationConverter.java │ │ │ │ ├── CustomConverterTest.java │ │ │ │ ├── CustomResolverTest.java │ │ │ │ ├── GenericModelConverter.java │ │ │ │ ├── ModelPropertyOverrideTest.java │ │ │ │ ├── OverrideTest.java │ │ │ │ ├── SamplePropertyConverter.java │ │ │ │ ├── SamplePropertyExtendedConverter.java │ │ │ │ ├── SnakeCaseConverterTest.java │ │ │ │ └── resources/ │ │ │ │ ├── GenericModel.java │ │ │ │ └── MyCustomClass.java │ │ │ ├── deserialization/ │ │ │ │ ├── ComprehensiveOAS31ValidationTest.java │ │ │ │ ├── JsonDeserializationTest.java │ │ │ │ ├── ObjectPropertyTest.java │ │ │ │ ├── OpenAPI3_1DeserializationTest.java │ │ │ │ ├── ParameterDeSerializationTest.java │ │ │ │ ├── SchemaDeserializationTest.java │ │ │ │ └── properties/ │ │ │ │ ├── ArrayPropertyDeserializerTest.java │ │ │ │ ├── JsonPropertiesDeserializationTest.java │ │ │ │ ├── MapPropertyDeserializerTest.java │ │ │ │ └── PropertyDeserializerTest.java │ │ │ ├── filter/ │ │ │ │ ├── SpecFilterTest.java │ │ │ │ └── resources/ │ │ │ │ ├── ChangeGetOperationsFilter.java │ │ │ │ ├── InternalModelPropertiesRemoverFilter.java │ │ │ │ ├── NoCategoryRefSchemaFilter.java │ │ │ │ ├── NoGetOperationsFilter.java │ │ │ │ ├── NoOpOperationsFilter.java │ │ │ │ ├── NoOpenAPIFilter.java │ │ │ │ ├── NoParametersWithoutQueryInFilter.java │ │ │ │ ├── NoPathItemFilter.java │ │ │ │ ├── NoPetOperationsFilter.java │ │ │ │ ├── NoPetRefSchemaFilter.java │ │ │ │ ├── NoTagRefSchemaPropertyFilter.java │ │ │ │ ├── RemoveInternalParamsFilter.java │ │ │ │ ├── RemoveUnreferencedDefinitionsFilter.java │ │ │ │ └── ReplaceGetOperationsFilter.java │ │ │ ├── issues/ │ │ │ │ ├── Issue4339Test.java │ │ │ │ ├── Issue4838Test.java │ │ │ │ └── Issue5001Test.java │ │ │ ├── matchers/ │ │ │ │ └── SerializationMatchers.java │ │ │ ├── oas/ │ │ │ │ └── models/ │ │ │ │ ├── Address.java │ │ │ │ ├── ApiFirstRequiredFieldModel.java │ │ │ │ ├── BeanValidationsModel.java │ │ │ │ ├── Car.java │ │ │ │ ├── Cat.java │ │ │ │ ├── Children.java │ │ │ │ ├── ClientOptInput.java │ │ │ │ ├── Department.java │ │ │ │ ├── Employee.java │ │ │ │ ├── EmptyModel.java │ │ │ │ ├── Error.java │ │ │ │ ├── GuavaModel.java │ │ │ │ ├── Issue534.java │ │ │ │ ├── JCovariantGetter.java │ │ │ │ ├── JacksonIntegerValueEnum.java │ │ │ │ ├── JacksonIntegerValueFieldEnum.java │ │ │ │ ├── JacksonPropertyEnum.java │ │ │ │ ├── JacksonReadonlyModel.java │ │ │ │ ├── JacksonValueEnum.java │ │ │ │ ├── JacksonValueFieldEnum.java │ │ │ │ ├── JacksonValuePrivateEnum.java │ │ │ │ ├── JodaDateTimeModel.java │ │ │ │ ├── Link.java │ │ │ │ ├── Manufacturers.java │ │ │ │ ├── Model1155.java │ │ │ │ ├── Model1979.java │ │ │ │ ├── ModelExampleTest.java │ │ │ │ ├── ModelPropertyName.java │ │ │ │ ├── ModelWithAltPropertyName.java │ │ │ │ ├── ModelWithApiModel.java │ │ │ │ ├── ModelWithArrayOfSubclasses.java │ │ │ │ ├── ModelWithBooleanProperty.java │ │ │ │ ├── ModelWithEnumArray.java │ │ │ │ ├── ModelWithEnumField.java │ │ │ │ ├── ModelWithEnumProperty.java │ │ │ │ ├── ModelWithEnumRefProperty.java │ │ │ │ ├── ModelWithFormattedStrings.java │ │ │ │ ├── ModelWithJAXBAnnotations.java │ │ │ │ ├── ModelWithJacksonEnumField.java │ │ │ │ ├── ModelWithJaxBDefaultValues.java │ │ │ │ ├── ModelWithModelPropertyOverrides.java │ │ │ │ ├── ModelWithNumbers.java │ │ │ │ ├── ModelWithOffset.java │ │ │ │ ├── ModelWithPrimitiveArray.java │ │ │ │ ├── ModelWithRanges.java │ │ │ │ ├── ModelWithTuple2.java │ │ │ │ ├── Person.java │ │ │ │ ├── ReadOnlyFields.java │ │ │ │ ├── ReadOnlyModel.java │ │ │ │ ├── RequiredFields.java │ │ │ │ ├── RequiredRefFieldModel.java │ │ │ │ ├── SpecialOrderItem.java │ │ │ │ ├── TestEnum.java │ │ │ │ ├── TestSecondEnum.java │ │ │ │ ├── XmlFirstRequiredFieldModel.java │ │ │ │ ├── composition/ │ │ │ │ │ ├── AbstractBaseModelWithSubTypes.java │ │ │ │ │ ├── AbstractBaseModelWithoutFields.java │ │ │ │ │ ├── AbstractModelWithApiModel.java │ │ │ │ │ ├── Animal.java │ │ │ │ │ ├── AnimalClass.java │ │ │ │ │ ├── AnimalWithSchemaSubtypes.java │ │ │ │ │ ├── Human.java │ │ │ │ │ ├── HumanClass.java │ │ │ │ │ ├── HumanWithSchemaSubtypes.java │ │ │ │ │ ├── ModelWithFieldWithSubTypes.java │ │ │ │ │ ├── ModelWithUrlProperty.java │ │ │ │ │ ├── ModelWithValueProperty.java │ │ │ │ │ ├── Pet.java │ │ │ │ │ ├── PetClass.java │ │ │ │ │ ├── PetWithSchemaSubtypes.java │ │ │ │ │ ├── Thing1.java │ │ │ │ │ ├── Thing2.java │ │ │ │ │ └── Thing3.java │ │ │ │ └── xmltest/ │ │ │ │ ├── NestedModelWithJAXBAnnotations.java │ │ │ │ ├── SubModelWithJAXBAnnotations.java │ │ │ │ └── package-info.java │ │ │ ├── resolving/ │ │ │ │ ├── ATMTest.java │ │ │ │ ├── AllofResolvingTest.java │ │ │ │ ├── AnnotationsUtilsExtensionsTest.java │ │ │ │ ├── AnnotationsUtilsHeadersTest.java │ │ │ │ ├── BeanValidatorTest.java │ │ │ │ ├── ComplexPropertyTest.java │ │ │ │ ├── ComposedSchemaTest.java │ │ │ │ ├── CompositionSuperfluousRefTest.java │ │ │ │ ├── ContainerTest.java │ │ │ │ ├── EnumTest.java │ │ │ │ ├── HiddenFieldTest.java │ │ │ │ ├── InheritedBeanTest.java │ │ │ │ ├── InlineResolvingTest.java │ │ │ │ ├── JacksonJsonUnwrappedTest.java │ │ │ │ ├── JaxBDefaultValueTest.java │ │ │ │ ├── JodaDateTimeConverterTest.java │ │ │ │ ├── JodaLocalDateConverterTest.java │ │ │ │ ├── JodaTest.java │ │ │ │ ├── JsonPropertyTest.java │ │ │ │ ├── JsonSubTypesAndSchemaOneOfTest.java │ │ │ │ ├── JsonViewTest.java │ │ │ │ ├── ModelWithRangesTest.java │ │ │ │ ├── RequiredFieldModelTest.java │ │ │ │ ├── SimpleGenerationTest.java │ │ │ │ ├── SwaggerTestBase.java │ │ │ │ ├── Ticket2189Test.java │ │ │ │ ├── Ticket2740CyclicTest.java │ │ │ │ ├── Ticket2862SubtypeTest.java │ │ │ │ ├── Ticket2884Test.java │ │ │ │ ├── Ticket2915Test.java │ │ │ │ ├── Ticket2926Test.java │ │ │ │ ├── Ticket2972Test.java │ │ │ │ ├── Ticket2992Test.java │ │ │ │ ├── Ticket3030Test.java │ │ │ │ ├── Ticket3063Test.java │ │ │ │ ├── Ticket3197Test.java │ │ │ │ ├── Ticket3348Test.java │ │ │ │ ├── Ticket3365Test.java │ │ │ │ ├── Ticket3624Test.java │ │ │ │ ├── Ticket3697Test.java │ │ │ │ ├── Ticket3699Test.java │ │ │ │ ├── Ticket3703Test.java │ │ │ │ ├── Ticket3853Test.java │ │ │ │ ├── Ticket3904Test.java │ │ │ │ ├── Ticket4239Test.java │ │ │ │ ├── Ticket4290Test.java │ │ │ │ ├── Ticket4362Test.java │ │ │ │ ├── Ticket4474Test.java │ │ │ │ ├── Ticket4679Test.java │ │ │ │ ├── Ticket4760Test.java │ │ │ │ ├── Ticket4771Test.java │ │ │ │ ├── Ticket4800Test.java │ │ │ │ ├── Ticket4904Test.java │ │ │ │ ├── XMLGregorianCalendarTest.java │ │ │ │ ├── XMLInfoTest.java │ │ │ │ ├── XmlModelTest.java │ │ │ │ ├── resources/ │ │ │ │ │ ├── BidimensionalArray.java │ │ │ │ │ ├── InnerType.java │ │ │ │ │ ├── InnerTypeRequired.java │ │ │ │ │ ├── Issue4290.java │ │ │ │ │ ├── JacksonUnwrappedRequiredProperty.java │ │ │ │ │ ├── JsonViewObject.java │ │ │ │ │ ├── MyThing.java │ │ │ │ │ ├── TestArrayType.java │ │ │ │ │ ├── TestObject2616.java │ │ │ │ │ ├── TestObject2915.java │ │ │ │ │ ├── TestObject2972.java │ │ │ │ │ ├── TestObject2992.java │ │ │ │ │ ├── TestObject3697.java │ │ │ │ │ ├── TestObject3699.java │ │ │ │ │ ├── TestObject4715.java │ │ │ │ │ ├── TestObjectTicket2620.java │ │ │ │ │ ├── TestObjectTicket2620Subtypes.java │ │ │ │ │ ├── TestObjectTicket2900.java │ │ │ │ │ ├── TestObjectTicket4247.java │ │ │ │ │ ├── Ticket2862Model.java │ │ │ │ │ ├── Ticket2862ModelImpl.java │ │ │ │ │ ├── Ticket2884Model.java │ │ │ │ │ ├── Ticket2884ModelClass.java │ │ │ │ │ └── User2169.java │ │ │ │ └── v31/ │ │ │ │ ├── ModelResolverOAS31Test.java │ │ │ │ ├── PatternAndSchemaPropertiesTest.java │ │ │ │ ├── StreamWithArraySchemaTest.java │ │ │ │ ├── Ticket3900Test.java │ │ │ │ └── model/ │ │ │ │ ├── Address.java │ │ │ │ ├── AnnotatedArray.java │ │ │ │ ├── AnnotatedArrayProperty.java │ │ │ │ ├── AnnotatedArrayPropertyReadWrite.java │ │ │ │ ├── AnnotatedArrayPropertyWriteOnly.java │ │ │ │ ├── AnnotatedPet.java │ │ │ │ ├── AnnotatedPetSinglePatternProperty.java │ │ │ │ ├── Category.java │ │ │ │ ├── Client.java │ │ │ │ ├── CreditCard.java │ │ │ │ ├── Currency.java │ │ │ │ ├── CustomGenerator.java │ │ │ │ ├── ExtensionUser.java │ │ │ │ ├── JacksonBean.java │ │ │ │ ├── ListOfStringsBeanParam.java │ │ │ │ ├── ModelWithDependentSchema.java │ │ │ │ ├── ModelWithJsonIdentity.java │ │ │ │ ├── ModelWithJsonIdentityCyclic.java │ │ │ │ ├── ModelWithOAS31Stuff.java │ │ │ │ ├── ModelWithOAS31StuffMinimal.java │ │ │ │ ├── MultipleBaseBean.java │ │ │ │ ├── MultipleSub1Bean.java │ │ │ │ ├── MultipleSub2Bean.java │ │ │ │ ├── NotFoundModel.java │ │ │ │ ├── Pet.java │ │ │ │ ├── PostalCodeNumberPattern.java │ │ │ │ ├── PostalCodePattern.java │ │ │ │ ├── Tag.java │ │ │ │ ├── User.java │ │ │ │ └── siblings/ │ │ │ │ ├── Category.java │ │ │ │ └── Pet.java │ │ │ ├── roundtrip/ │ │ │ │ └── ComprehensiveRoundTripTest.java │ │ │ ├── serialization/ │ │ │ │ ├── ComprehensiveSerializationTest.java │ │ │ │ ├── JsonSerializationTest.java │ │ │ │ ├── ModelSerializerTest.java │ │ │ │ ├── Oas31ObjectFieldTest.java │ │ │ │ ├── OpenAPI3_1SerializationTest.java │ │ │ │ ├── ParameterSerializationTest.java │ │ │ │ ├── ResponseExamplesTest.java │ │ │ │ ├── SchemaSerializationTest.java │ │ │ │ ├── SecurityDefinitionTest.java │ │ │ │ ├── YamlSerializerTest.java │ │ │ │ ├── auth/ │ │ │ │ │ └── AuthSerializationTest.java_ │ │ │ │ └── properties/ │ │ │ │ └── PropertySerializationTest.java │ │ │ └── util/ │ │ │ ├── AnnotationsUtilsTest.java │ │ │ ├── JsonAssert.java │ │ │ ├── OutputReplacer.java │ │ │ ├── PathUtilsTest.java │ │ │ ├── ReferenceTypeUtilsTest.java │ │ │ ├── ResourceUtils.java │ │ │ ├── TestUtils.java │ │ │ ├── ValidationAnnotationsUtilsTest.java │ │ │ └── reflection/ │ │ │ ├── ReflectionUtilsTest.java │ │ │ └── resources/ │ │ │ ├── Child.java │ │ │ ├── IGrandparent.java │ │ │ ├── IParent.java │ │ │ ├── IndirectAnnotation.java │ │ │ ├── ObjectWithManyFields.java │ │ │ └── Parent.java │ │ └── resources/ │ │ ├── AbstractBaseModelWithoutFields.json │ │ ├── Animal.json │ │ ├── AnimalClass.json │ │ ├── AnimalWithSchemaSubtypes.json │ │ ├── Cat.json │ │ ├── GuavaTestModel.json │ │ ├── Human.json │ │ ├── JodaDateTimeModel.json │ │ ├── ModelWithFieldWithSubTypes.json │ │ ├── ModelWithFormattedStrings.json │ │ ├── ModelWithSecurityRequirements.json │ │ ├── Person.json │ │ ├── Pet.json │ │ ├── comprehensiveOAS31/ │ │ │ ├── comprehensive-openapi.yaml │ │ │ ├── paths/ │ │ │ │ ├── order-paths.yaml │ │ │ │ ├── pet-paths.yaml │ │ │ │ └── user-paths.yaml │ │ │ └── schemas/ │ │ │ ├── common-schemas.yaml │ │ │ ├── json-schema.yaml │ │ │ ├── order-schemas.yaml │ │ │ ├── pet-schemas.yaml │ │ │ └── user-schemas.yaml │ │ ├── converting/ │ │ │ ├── ArrayOfSubclassTest_expected30.json │ │ │ └── ArrayOfSubclassTest_expected31.json │ │ ├── dateSchema.yaml │ │ ├── json-schema-validation/ │ │ │ ├── array.json │ │ │ └── map.json │ │ ├── logback-test.xml │ │ ├── specFiles/ │ │ │ ├── 3.1.0/ │ │ │ │ ├── changelog-3.1.yaml │ │ │ │ ├── composed-schema-3.1.json │ │ │ │ ├── issue-4737-3.1.yaml │ │ │ │ ├── list-3.1.json │ │ │ │ ├── petstore-3.1.json │ │ │ │ ├── petstore-3.1.yaml │ │ │ │ ├── petstore-3.1_more.yaml │ │ │ │ ├── petstore-3.1_refs_siblings.yaml │ │ │ │ ├── petstore-3.1_sample.yaml │ │ │ │ ├── specWithDynamicRef.yaml │ │ │ │ └── specWithReferredSchemas-3.1.yaml │ │ │ ├── additionalpropsmodel.json │ │ │ ├── brokenrefmodel.json │ │ │ ├── compositionTest-3.0.json │ │ │ ├── compositionTest.json │ │ │ ├── deprecatedoperationmodel.json │ │ │ ├── jsonSerialization-expected-petstore-3.0.json │ │ │ ├── media-type-null-example.yaml │ │ │ ├── noModels.json │ │ │ ├── null-example.yaml │ │ │ ├── null-in-schema-example.yaml │ │ │ ├── oas3.yaml │ │ │ ├── oas3_2.yaml │ │ │ ├── paramAndResponseRef.json │ │ │ ├── paramAndResponseRefArray.json │ │ │ ├── paramAndResponseRefComposed.json │ │ │ ├── pathRef.json │ │ │ ├── petstore-3.0-referred-schemas.json │ │ │ ├── petstore-3.0-v2-ticket-3303.json │ │ │ ├── petstore-3.0-v2.json │ │ │ ├── petstore-3.0-v2_withoutModels.json │ │ │ ├── petstore-3.0.json │ │ │ ├── petstore-3.0.yaml │ │ │ ├── petstore.json │ │ │ ├── propertiesWithConstraints.json │ │ │ ├── propertyWithVendorExtensions.json │ │ │ ├── recursivemodels.json │ │ │ ├── responseRef.json │ │ │ ├── sampleSpec.json │ │ │ ├── securityDefinitions.json │ │ │ ├── securitySchemaWithExtension.json │ │ │ └── swos-126.yaml │ │ ├── testOAS31/ │ │ │ └── basicOAS31.yaml │ │ └── uber.json │ ├── swagger-eclipse-transformer-maven-plugin/ │ │ ├── README.md │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── io/ │ │ └── swagger/ │ │ └── v3/ │ │ └── oas/ │ │ └── transformer/ │ │ └── TransformMojo.java │ ├── swagger-gradle-plugin/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── build.gradle │ │ ├── gradle/ │ │ │ └── wrapper/ │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ ├── settings.gradle │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── io/ │ │ │ └── swagger/ │ │ │ └── v3/ │ │ │ └── plugins/ │ │ │ └── gradle/ │ │ │ ├── SwaggerPlugin.java │ │ │ └── tasks/ │ │ │ └── ResolveTask.java │ │ └── test/ │ │ └── java/ │ │ └── io/ │ │ └── swagger/ │ │ └── v3/ │ │ └── plugins/ │ │ └── gradle/ │ │ ├── SwaggerResolveTest.java │ │ ├── petstore/ │ │ │ ├── EmptyPetResource.java │ │ │ ├── PetResource.java │ │ │ ├── callback/ │ │ │ │ ├── ComplexCallbackResource.java │ │ │ │ ├── MultipleCallbacksTestWithOperationResource.java │ │ │ │ ├── RepeatableCallbackResource.java │ │ │ │ └── SimpleCallbackWithOperationResource.java │ │ │ ├── example/ │ │ │ │ ├── ExamplesResource.java │ │ │ │ └── SubscriptionResponse.java │ │ │ ├── link/ │ │ │ │ └── LinksResource.java │ │ │ ├── openapidefintion/ │ │ │ │ └── OpenAPIDefinitionResource.java │ │ │ ├── operation/ │ │ │ │ ├── AnnotatedSameNameOperationResource.java │ │ │ │ ├── ExternalDocumentationResource.java │ │ │ │ ├── FullyAnnotatedOperationResource.java │ │ │ │ ├── HiddenOperationResource.java │ │ │ │ ├── InterfaceResource.java │ │ │ │ ├── NotAnnotatedSameNameOperationResource.java │ │ │ │ ├── OperationResource.java │ │ │ │ ├── OperationWithoutAnnotationResource.java │ │ │ │ ├── ServerOperationResource.java │ │ │ │ └── SubResource.java │ │ │ ├── parameter/ │ │ │ │ ├── ArraySchemaResource.java │ │ │ │ ├── ComplexParameterResource.java │ │ │ │ ├── ComplexParameterWithOperationResource.java │ │ │ │ ├── MultipleNotAnnotatedParameter.java │ │ │ │ ├── OpenAPIJaxRSAnnotatedParameter.java │ │ │ │ ├── OpenAPIWithContentJaxRSAnnotatedParameter.java │ │ │ │ ├── OpenAPIWithImplementationJaxRSAnnotatedParameter.java │ │ │ │ ├── ParametersResource.java │ │ │ │ ├── RepeatableParametersResource.java │ │ │ │ ├── SingleJaxRSAnnotatedParameter.java │ │ │ │ └── SingleNotAnnotatedParameter.java │ │ │ ├── requestbody/ │ │ │ │ ├── RequestBodyMethodPriorityResource.java │ │ │ │ ├── RequestBodyParameterPriorityResource.java │ │ │ │ └── RequestBodyResource.java │ │ │ ├── responses/ │ │ │ │ ├── ComplexResponseResource.java │ │ │ │ ├── ImplementationResponseResource.java │ │ │ │ ├── MethodResponseResource.java │ │ │ │ ├── NoImplementationResponseResource.java │ │ │ │ ├── NoResponseResource.java │ │ │ │ ├── OperationResponseResource.java │ │ │ │ └── PriorityResponseResource.java │ │ │ ├── security/ │ │ │ │ └── SecurityResource.java │ │ │ └── tags/ │ │ │ ├── CompleteTagResource.java │ │ │ ├── TagClassResource.java │ │ │ ├── TagMethodResource.java │ │ │ ├── TagOpenAPIDefinitionResource.java │ │ │ └── TagOperationResource.java │ │ └── resources/ │ │ ├── MyFilter.java │ │ ├── QueryResultBean.java │ │ ├── data/ │ │ │ ├── PetData.java │ │ │ └── UserData.java │ │ ├── exception/ │ │ │ ├── ApiException.java │ │ │ └── NotFoundException.java │ │ └── model/ │ │ ├── Category.java │ │ ├── CustomGenerator.java │ │ ├── ExtensionUser.java │ │ ├── JacksonBean.java │ │ ├── ListOfStringsBeanParam.java │ │ ├── ModelWithJsonIdentity.java │ │ ├── ModelWithJsonIdentityCyclic.java │ │ ├── MultipleBaseBean.java │ │ ├── MultipleSub1Bean.java │ │ ├── MultipleSub2Bean.java │ │ ├── NotFoundModel.java │ │ ├── Pet.java │ │ ├── Tag.java │ │ └── User.java │ ├── swagger-integration/ │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── io/ │ │ │ └── swagger/ │ │ │ └── v3/ │ │ │ └── oas/ │ │ │ └── integration/ │ │ │ ├── ClasspathOpenApiConfigurationLoader.java │ │ │ ├── ContextUtils.java │ │ │ ├── FileOpenApiConfigurationLoader.java │ │ │ ├── GenericOpenApiContext.java │ │ │ ├── GenericOpenApiContextBuilder.java │ │ │ ├── GenericOpenApiScanner.java │ │ │ ├── IgnoredPackages.java │ │ │ ├── IntegrationObjectMapperFactory.java │ │ │ ├── OpenApiConfigurationException.java │ │ │ ├── OpenApiContextLocator.java │ │ │ ├── ServiceOpenApiConfigurationLoader.java │ │ │ ├── StringOpenApiConfigurationLoader.java │ │ │ ├── SwaggerConfiguration.java │ │ │ ├── URLOpenApiConfigurationLoader.java │ │ │ └── api/ │ │ │ ├── ObjectMapperProcessor.java │ │ │ ├── OpenAPIConfigBuilder.java │ │ │ ├── OpenAPIConfiguration.java │ │ │ ├── OpenApiConfigurationLoader.java │ │ │ ├── OpenApiContext.java │ │ │ ├── OpenApiContextBuilder.java │ │ │ ├── OpenApiReader.java │ │ │ └── OpenApiScanner.java │ │ └── test/ │ │ └── java/ │ │ └── io/ │ │ └── swagger/ │ │ └── v3/ │ │ └── oas/ │ │ └── integration/ │ │ └── IntegrationTest.java │ ├── swagger-java17-support/ │ │ ├── pom.xml │ │ └── src/ │ │ └── test/ │ │ └── java/ │ │ └── io/ │ │ └── swagger/ │ │ └── v3/ │ │ └── java17/ │ │ ├── Reader/ │ │ │ ├── ReaderTest.java │ │ │ └── SchemaResolutionRecordsTest.java │ │ ├── matchers/ │ │ │ └── SerializationMatchers.java │ │ ├── resolving/ │ │ │ ├── JavaRecordTest.java │ │ │ ├── SwaggerTestBase.java │ │ │ └── v31/ │ │ │ └── ModelResolverOAS31Test.java │ │ └── resources/ │ │ ├── JavaRecordResource.java │ │ ├── JavaRecordWithPathResource.java │ │ ├── OtherJavaRecordWithPathsResource.java │ │ ├── SchemaResolutionWithRecordSimpleResource.java │ │ ├── SchemaResolutionWithRecordsResource.java │ │ └── TestControllerWithRecordResource.java │ ├── swagger-jaxrs2/ │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ ├── java/ │ │ │ │ └── io/ │ │ │ │ └── swagger/ │ │ │ │ └── v3/ │ │ │ │ └── jaxrs2/ │ │ │ │ ├── DefaultParameterExtension.java │ │ │ │ ├── OperationParser.java │ │ │ │ ├── Reader.java │ │ │ │ ├── ReaderListener.java │ │ │ │ ├── ResolvedParameter.java │ │ │ │ ├── SecurityParser.java │ │ │ │ ├── SwaggerSerializers.java │ │ │ │ ├── ext/ │ │ │ │ │ ├── AbstractOpenAPIExtension.java │ │ │ │ │ ├── OpenAPIExtension.java │ │ │ │ │ └── OpenAPIExtensions.java │ │ │ │ ├── integration/ │ │ │ │ │ ├── JaxrsAnnotationScanner.java │ │ │ │ │ ├── JaxrsApplicationAndAnnotationScanner.java │ │ │ │ │ ├── JaxrsApplicationAndResourcePackagesAnnotationScanner.java │ │ │ │ │ ├── JaxrsApplicationScanner.java │ │ │ │ │ ├── JaxrsOpenApiContext.java │ │ │ │ │ ├── JaxrsOpenApiContextBuilder.java │ │ │ │ │ ├── OpenApiServlet.java │ │ │ │ │ ├── ServletConfigContextUtils.java │ │ │ │ │ ├── ServletOpenApiConfigurationLoader.java │ │ │ │ │ ├── ServletOpenApiContextBuilder.java │ │ │ │ │ ├── ServletPathConfigurationLoader.java │ │ │ │ │ ├── SwaggerLoader.java │ │ │ │ │ ├── XmlWebOpenApiContext.java │ │ │ │ │ ├── api/ │ │ │ │ │ │ ├── JaxrsOpenApiScanner.java │ │ │ │ │ │ └── WebOpenApiContext.java │ │ │ │ │ └── resources/ │ │ │ │ │ ├── AcceptHeaderOpenApiResource.java │ │ │ │ │ ├── BaseOpenApiResource.java │ │ │ │ │ └── OpenApiResource.java │ │ │ │ └── util/ │ │ │ │ ├── ReaderUtils.java │ │ │ │ └── ServletUtils.java │ │ │ └── resources/ │ │ │ └── META-INF/ │ │ │ └── beans.xml │ │ └── test/ │ │ ├── java/ │ │ │ ├── com/ │ │ │ │ └── my/ │ │ │ │ ├── project/ │ │ │ │ │ └── resources/ │ │ │ │ │ └── ResourceInPackageA.java │ │ │ │ └── sorted/ │ │ │ │ └── resources/ │ │ │ │ └── SortedThing.java │ │ │ ├── io/ │ │ │ │ └── swagger/ │ │ │ │ └── v3/ │ │ │ │ └── jaxrs2/ │ │ │ │ ├── BeanParamTest.java │ │ │ │ ├── BinaryParameterResourceTest.java │ │ │ │ ├── BootstrapServlet.java │ │ │ │ ├── ContainerTypeSchemaTicket2636Test.java │ │ │ │ ├── DecoratorExtensionTest.java │ │ │ │ ├── EnumTest.java │ │ │ │ ├── FormParamBeanTest.java │ │ │ │ ├── JaxbObjectMapperFactory.java │ │ │ │ ├── JsonIdentityTest.java │ │ │ │ ├── JsonViewTest.java │ │ │ │ ├── PetResourceTest.java │ │ │ │ ├── ReaderTest.java │ │ │ │ ├── SchemaResolutionAllOfRefTest.java │ │ │ │ ├── SchemaResolutionAllOfTest.java │ │ │ │ ├── SchemaResolutionAnnotationTest.java │ │ │ │ ├── SchemaResolutionInlineTest.java │ │ │ │ ├── annotations/ │ │ │ │ │ ├── AbstractAnnotationTest.java │ │ │ │ │ ├── callbacks/ │ │ │ │ │ │ └── CallbackTest.java │ │ │ │ │ ├── definition/ │ │ │ │ │ │ └── OpenApiDefinitionTest.java │ │ │ │ │ ├── encoding/ │ │ │ │ │ │ └── EncodingTest.java │ │ │ │ │ ├── examples/ │ │ │ │ │ │ └── ExamplesTest.java │ │ │ │ │ ├── info/ │ │ │ │ │ │ └── InfoTest.java │ │ │ │ │ ├── operations/ │ │ │ │ │ │ ├── AnnotatedOperationMethodTest.java │ │ │ │ │ │ └── MergedOperationTest.java │ │ │ │ │ ├── parameters/ │ │ │ │ │ │ └── ParametersTest.java │ │ │ │ │ ├── pathItems/ │ │ │ │ │ │ └── OperationsWithLinksTest.java │ │ │ │ │ ├── readerListener/ │ │ │ │ │ │ └── ReaderListenerTest.java │ │ │ │ │ ├── requests/ │ │ │ │ │ │ └── RequestBodyTest.java │ │ │ │ │ └── security/ │ │ │ │ │ └── SecurityTest.java │ │ │ │ ├── cdi2/ │ │ │ │ │ ├── CDIAutodiscoveryTest.java │ │ │ │ │ └── DiscoveryTestExtension.java │ │ │ │ ├── integration/ │ │ │ │ │ ├── JaxrsApplicationAndAnnotationScannerTest.java │ │ │ │ │ ├── JaxrsApplicationAndResourcePackagesAnnotationScannerTest.java │ │ │ │ │ ├── JaxrsApplicationScannerTest.java │ │ │ │ │ └── SortedOutputTest.java │ │ │ │ ├── it/ │ │ │ │ │ ├── OpenApiResourceIT.java │ │ │ │ │ ├── model/ │ │ │ │ │ │ └── Widget.java │ │ │ │ │ └── resources/ │ │ │ │ │ ├── CarResource.java │ │ │ │ │ ├── MultiPartFileResource.java │ │ │ │ │ ├── OctetStreamResource.java │ │ │ │ │ ├── UrlEncodedResource.java │ │ │ │ │ └── WidgetResource.java │ │ │ │ ├── matchers/ │ │ │ │ │ └── SerializationMatchers.java │ │ │ │ ├── petstore/ │ │ │ │ │ ├── EmptyPetResource.java │ │ │ │ │ ├── PetResource.java │ │ │ │ │ ├── WebHookResource.java │ │ │ │ │ ├── callback/ │ │ │ │ │ │ ├── ComplexCallback31Resource.java │ │ │ │ │ │ ├── ComplexCallbackResource.java │ │ │ │ │ │ ├── MultipleCallbacksTestWithOperationResource.java │ │ │ │ │ │ ├── RepeatableCallbackResource.java │ │ │ │ │ │ └── SimpleCallbackWithOperationResource.java │ │ │ │ │ ├── example/ │ │ │ │ │ │ ├── ExamplesResource.java │ │ │ │ │ │ └── SubscriptionResponse.java │ │ │ │ │ ├── link/ │ │ │ │ │ │ ├── LinksAndContent31Resource.java │ │ │ │ │ │ └── LinksResource.java │ │ │ │ │ ├── openapidefintion/ │ │ │ │ │ │ ├── OpenAPI31DefinitionResource.java │ │ │ │ │ │ └── OpenAPIDefinitionResource.java │ │ │ │ │ ├── operation/ │ │ │ │ │ │ ├── AnnotatedSameNameOperationResource.java │ │ │ │ │ │ ├── ExternalDocumentationResource.java │ │ │ │ │ │ ├── FullyAnnotatedOperationResource.java │ │ │ │ │ │ ├── HiddenOperationResource.java │ │ │ │ │ │ ├── InterfaceResource.java │ │ │ │ │ │ ├── NotAnnotatedSameNameOperationResource.java │ │ │ │ │ │ ├── OperationResource.java │ │ │ │ │ │ ├── OperationWithoutAnnotationResource.java │ │ │ │ │ │ ├── ServerOperationResource.java │ │ │ │ │ │ └── SubResource.java │ │ │ │ │ ├── parameter/ │ │ │ │ │ │ ├── ArraySchemaResource.java │ │ │ │ │ │ ├── ComplexParameterResource.java │ │ │ │ │ │ ├── ComplexParameterWithOperationResource.java │ │ │ │ │ │ ├── MultipleNotAnnotatedParameter.java │ │ │ │ │ │ ├── OpenAPIJaxRSAnnotatedParameter.java │ │ │ │ │ │ ├── OpenAPIWithContentJaxRSAnnotatedParameter.java │ │ │ │ │ │ ├── OpenAPIWithImplementationJaxRSAnnotatedParameter.java │ │ │ │ │ │ ├── Parameters31Resource.java │ │ │ │ │ │ ├── ParametersResource.java │ │ │ │ │ │ ├── RepeatableParametersResource.java │ │ │ │ │ │ ├── SingleJaxRSAnnotatedParameter.java │ │ │ │ │ │ └── SingleNotAnnotatedParameter.java │ │ │ │ │ ├── requestbody/ │ │ │ │ │ │ ├── RequestBody31Resource.java │ │ │ │ │ │ ├── RequestBodyMethodPriorityResource.java │ │ │ │ │ │ ├── RequestBodyParameterPriorityResource.java │ │ │ │ │ │ └── RequestBodyResource.java │ │ │ │ │ ├── responses/ │ │ │ │ │ │ ├── ComplexResponseResource.java │ │ │ │ │ │ ├── ImplementationResponseResource.java │ │ │ │ │ │ ├── MethodArrayResponseResource.java │ │ │ │ │ │ ├── MethodResponseResource.java │ │ │ │ │ │ ├── NoImplementationResponseResource.java │ │ │ │ │ │ ├── NoResponseResource.java │ │ │ │ │ │ ├── OperationResponseResource.java │ │ │ │ │ │ └── PriorityResponseResource.java │ │ │ │ │ ├── security/ │ │ │ │ │ │ └── SecurityResource.java │ │ │ │ │ └── tags/ │ │ │ │ │ ├── CompleteTagResource.java │ │ │ │ │ ├── TagClassResource.java │ │ │ │ │ ├── TagMethodResource.java │ │ │ │ │ ├── TagOpenAPIDefinitionResource.java │ │ │ │ │ └── TagOperationResource.java │ │ │ │ ├── petstore31/ │ │ │ │ │ ├── Category.java │ │ │ │ │ ├── Pet.java │ │ │ │ │ ├── PetData.java │ │ │ │ │ ├── PetResource.java │ │ │ │ │ ├── SimpleCategory.java │ │ │ │ │ ├── SimpleTag.java │ │ │ │ │ ├── Tag.java │ │ │ │ │ ├── TagResource.java │ │ │ │ │ └── User.java │ │ │ │ ├── resources/ │ │ │ │ │ ├── Address.java │ │ │ │ │ ├── ArraySchemaImplementationResource.java │ │ │ │ │ ├── BasicClass.java │ │ │ │ │ ├── BasicFieldsResource.java │ │ │ │ │ ├── BinaryParameterResource.java │ │ │ │ │ ├── BookStoreTicket2646.java │ │ │ │ │ ├── ClassPathParentResource.java │ │ │ │ │ ├── ClassPathSubResource.java │ │ │ │ │ ├── Client.java │ │ │ │ │ ├── CompleteFieldsResource.java │ │ │ │ │ ├── CreditCard.java │ │ │ │ │ ├── DefaultResponseResource.java │ │ │ │ │ ├── DeprecatedFieldsResource.java │ │ │ │ │ ├── DuplicatedOperationIdResource.java │ │ │ │ │ ├── DuplicatedOperationMethodNameResource.java │ │ │ │ │ ├── DuplicatedSecurityResource.java │ │ │ │ │ ├── EnhancedResponsesResource.java │ │ │ │ │ ├── EnumParameterResource.java │ │ │ │ │ ├── ExternalDocsReference.java │ │ │ │ │ ├── GenericResponsesResource.java │ │ │ │ │ ├── HiddenAnnotatedUserResource.java │ │ │ │ │ ├── HiddenUserResource.java │ │ │ │ │ ├── JsonIdentityCyclicResource.java │ │ │ │ │ ├── JsonIdentityResource.java │ │ │ │ │ ├── Misc31Resource.java │ │ │ │ │ ├── ModelWithOAS31Stuff.java │ │ │ │ │ ├── MyClass.java │ │ │ │ │ ├── MyOtherClass.java │ │ │ │ │ ├── MySuperClass.java │ │ │ │ │ ├── NoPathSubResource.java │ │ │ │ │ ├── ParameterMaximumValueResource.java │ │ │ │ │ ├── ParametersResource.java │ │ │ │ │ ├── PetResource.java │ │ │ │ │ ├── PetResourceSlashesinPath.java │ │ │ │ │ ├── PostalCodeNumberPattern.java │ │ │ │ │ ├── PostalCodePattern.java │ │ │ │ │ ├── QueryResultBean.java │ │ │ │ │ ├── ReaderListenerResource.java │ │ │ │ │ ├── RefCallbackResource.java │ │ │ │ │ ├── RefExamplesResource.java │ │ │ │ │ ├── RefHeaderResource.java │ │ │ │ │ ├── RefLinksResource.java │ │ │ │ │ ├── RefParameter3029Resource.java │ │ │ │ │ ├── RefParameter3074Resource.java │ │ │ │ │ ├── RefParameterResource.java │ │ │ │ │ ├── RefRequestBodyResource.java │ │ │ │ │ ├── RefResponsesResource.java │ │ │ │ │ ├── RefSecurityResource.java │ │ │ │ │ ├── ResourceWithJacksonBean.java │ │ │ │ │ ├── ResourceWithKnownInjections.java │ │ │ │ │ ├── ResourceWithSubResource.java │ │ │ │ │ ├── ResponseContentWithArrayResource.java │ │ │ │ │ ├── ResponseReturnTypeResource.java │ │ │ │ │ ├── ResponsesInterface.java │ │ │ │ │ ├── ResponsesResource.java │ │ │ │ │ ├── SchemaAdditionalPropertiesBooleanResource.java │ │ │ │ │ ├── SchemaAdditionalPropertiesResource.java │ │ │ │ │ ├── SchemaPropertiesResource.java │ │ │ │ │ ├── SecurityResource.java │ │ │ │ │ ├── ServersResource.java │ │ │ │ │ ├── SiblingPropResource.java │ │ │ │ │ ├── SiblingsResource.java │ │ │ │ │ ├── SiblingsResourceRequestBody.java │ │ │ │ │ ├── SiblingsResourceRequestBodyMultiple.java │ │ │ │ │ ├── SiblingsResourceResponse.java │ │ │ │ │ ├── SiblingsResourceSimple.java │ │ │ │ │ ├── SimpleCallbackResource.java │ │ │ │ │ ├── SimpleExamplesResource.java │ │ │ │ │ ├── SimpleMethods.java │ │ │ │ │ ├── SimpleParameterResource.java │ │ │ │ │ ├── SimpleRequestBodyResource.java │ │ │ │ │ ├── SimpleResourceWithVendorAnnotation.java │ │ │ │ │ ├── SimpleResponsesResource.java │ │ │ │ │ ├── SimpleUserResource.java │ │ │ │ │ ├── SingleExampleResource.java │ │ │ │ │ ├── SubResource.java │ │ │ │ │ ├── SubResourceHead.java │ │ │ │ │ ├── SubResourceTail.java │ │ │ │ │ ├── TagsResource.java │ │ │ │ │ ├── Test2607.java │ │ │ │ │ ├── TestResource.java │ │ │ │ │ ├── TestSub2607.java │ │ │ │ │ ├── TestSubResource.java │ │ │ │ │ ├── Ticket2340Resource.java │ │ │ │ │ ├── Ticket2644AnnotatedInterface.java │ │ │ │ │ ├── Ticket2644ConcreteImplementation.java │ │ │ │ │ ├── Ticket2763Resource.java │ │ │ │ │ ├── Ticket2793Resource.java │ │ │ │ │ ├── Ticket2794Resource.java │ │ │ │ │ ├── Ticket2806Resource.java │ │ │ │ │ ├── Ticket2818Resource.java │ │ │ │ │ ├── Ticket2848Resource.java │ │ │ │ │ ├── Ticket3015Resource.java │ │ │ │ │ ├── Ticket3587Resource.java │ │ │ │ │ ├── Ticket3731BisResource.java │ │ │ │ │ ├── Ticket3731Resource.java │ │ │ │ │ ├── Ticket4065Resource.java │ │ │ │ │ ├── Ticket4341Resource.java │ │ │ │ │ ├── Ticket4412Resource.java │ │ │ │ │ ├── Ticket4446Resource.java │ │ │ │ │ ├── Ticket4483Resource.java │ │ │ │ │ ├── Ticket4804CustomClass.java │ │ │ │ │ ├── Ticket4804NotBlankResource.java │ │ │ │ │ ├── Ticket4804ProcessorResource.java │ │ │ │ │ ├── Ticket4804Resource.java │ │ │ │ │ ├── Ticket4850Resource.java │ │ │ │ │ ├── Ticket4859Resource.java │ │ │ │ │ ├── Ticket4878Resource.java │ │ │ │ │ ├── Ticket4879Resource.java │ │ │ │ │ ├── Ticket5017Resource.java │ │ │ │ │ ├── UploadRequest.java │ │ │ │ │ ├── UploadResource.java │ │ │ │ │ ├── UrlEncodedResourceWithEncodings.java │ │ │ │ │ ├── UserAnnotation.java │ │ │ │ │ ├── UserAnnotationResource.java │ │ │ │ │ ├── UserResource.java │ │ │ │ │ ├── WebHookResource.java │ │ │ │ │ ├── data/ │ │ │ │ │ │ ├── PetData.java │ │ │ │ │ │ └── UserData.java │ │ │ │ │ ├── exception/ │ │ │ │ │ │ ├── ApiException.java │ │ │ │ │ │ └── NotFoundException.java │ │ │ │ │ ├── extensions/ │ │ │ │ │ │ ├── ExtensionsResource.java │ │ │ │ │ │ ├── OperationExtensionsResource.java │ │ │ │ │ │ ├── ParameterExtensionsResource.java │ │ │ │ │ │ └── RequestBodyExtensionsResource.java │ │ │ │ │ ├── generics/ │ │ │ │ │ │ ├── ticket2144/ │ │ │ │ │ │ │ ├── BaseDTO.java │ │ │ │ │ │ │ ├── BaseResource.java │ │ │ │ │ │ │ ├── Item.java │ │ │ │ │ │ │ ├── ItemResource.java │ │ │ │ │ │ │ └── ItemWithChildren.java │ │ │ │ │ │ ├── ticket3149/ │ │ │ │ │ │ │ ├── AggregateEndpoint.java │ │ │ │ │ │ │ ├── FirstEndpoint.java │ │ │ │ │ │ │ ├── MainResource.java │ │ │ │ │ │ │ ├── OriginalEndpoint.java │ │ │ │ │ │ │ ├── SampleDTO.java │ │ │ │ │ │ │ ├── SampleOtherDTO.java │ │ │ │ │ │ │ └── SecondEndpoint.java │ │ │ │ │ │ ├── ticket3426/ │ │ │ │ │ │ │ ├── Parent.java │ │ │ │ │ │ │ └── Ticket3426Resource.java │ │ │ │ │ │ └── ticket3694/ │ │ │ │ │ │ ├── Ticket3694Resource.java │ │ │ │ │ │ ├── Ticket3694ResourceExtendedType.java │ │ │ │ │ │ ├── Ticket3694ResourceInterface.java │ │ │ │ │ │ ├── Ticket3694ResourceInterfaceExtendedType.java │ │ │ │ │ │ ├── Ticket3694ResourceInterfaceSimple.java │ │ │ │ │ │ ├── Ticket3694ResourceInterfaceSimpleSameReturn.java │ │ │ │ │ │ ├── Ticket3694ResourceSimple.java │ │ │ │ │ │ └── Ticket3694ResourceSimpleSameReturn.java │ │ │ │ │ ├── model/ │ │ │ │ │ │ ├── Category.java │ │ │ │ │ │ ├── CustomGenerator.java │ │ │ │ │ │ ├── ExtensionUser.java │ │ │ │ │ │ ├── FormParamBean.java │ │ │ │ │ │ ├── Item.java │ │ │ │ │ │ ├── JacksonBean.java │ │ │ │ │ │ ├── ListOfStringsBeanParam.java │ │ │ │ │ │ ├── ModelWithJsonIdentity.java │ │ │ │ │ │ ├── ModelWithJsonIdentityCyclic.java │ │ │ │ │ │ ├── MultipleBaseBean.java │ │ │ │ │ │ ├── MultipleSub1Bean.java │ │ │ │ │ │ ├── MultipleSub2Bean.java │ │ │ │ │ │ ├── NestedBeanParam.java │ │ │ │ │ │ ├── NotFoundModel.java │ │ │ │ │ │ ├── Pet.java │ │ │ │ │ │ ├── Tag.java │ │ │ │ │ │ └── User.java │ │ │ │ │ ├── rs/ │ │ │ │ │ │ ├── AbstractEntityRestService.java │ │ │ │ │ │ ├── EntityRestService.java │ │ │ │ │ │ ├── PersistentDTO.java │ │ │ │ │ │ ├── ProcessTokenDTO.java │ │ │ │ │ │ └── ProcessTokenRestService.java │ │ │ │ │ ├── siblings/ │ │ │ │ │ │ ├── Category.java │ │ │ │ │ │ ├── Pet.java │ │ │ │ │ │ └── PetSimple.java │ │ │ │ │ └── ticket3624/ │ │ │ │ │ ├── Service.java │ │ │ │ │ └── model/ │ │ │ │ │ ├── ByIdResponse.java │ │ │ │ │ ├── ContainerizedResponse.java │ │ │ │ │ ├── Model.java │ │ │ │ │ ├── ModelContainer.java │ │ │ │ │ └── Response.java │ │ │ │ ├── schemaResolution/ │ │ │ │ │ ├── SchemaResolutionAnnotatedResource.java │ │ │ │ │ ├── SchemaResolutionAnnotatedSimpleResource.java │ │ │ │ │ ├── SchemaResolutionResource.java │ │ │ │ │ └── SchemaResolutionResourceSimple.java │ │ │ │ └── util/ │ │ │ │ └── ServletUtilsTest.java │ │ │ └── org/ │ │ │ └── my/ │ │ │ └── project/ │ │ │ └── resources/ │ │ │ └── ResourceInPackageB.java │ │ ├── resources/ │ │ │ ├── BinaryParameterResource.yaml │ │ │ ├── examples/ │ │ │ │ ├── AnnotatedModelAndContentExample.yaml │ │ │ │ ├── AnnotatedModelExample.yaml │ │ │ │ ├── ParameterExample.yaml │ │ │ │ ├── RequestBodyContentExample.yaml │ │ │ │ ├── RequestBodyContentExampleWithConsumes.yaml │ │ │ │ ├── RequestBodyContentExampleWithMediatype.yaml │ │ │ │ ├── RequestBodyContentExampleWithSchema.yaml │ │ │ │ ├── RequestBodyContentExampleWithSchemaImplementation.yaml │ │ │ │ ├── ResponseExample.yaml │ │ │ │ ├── ResponseExampleSchema.yaml │ │ │ │ └── ResponseExampleSchemaImplementation.yaml │ │ │ ├── integration/ │ │ │ │ └── openapi-configuration.json │ │ │ ├── logback-test.xml │ │ │ └── petstore/ │ │ │ ├── EmptyPetResource.yaml │ │ │ ├── FullPetResource.yaml │ │ │ ├── OpenAPI31DefinitionResource.yaml │ │ │ ├── OpenAPIDefinitionResource.yaml │ │ │ ├── SecurityResource.yaml │ │ │ ├── WebHookResource.yaml │ │ │ ├── callbacks/ │ │ │ │ ├── ComplexCallback31Resource.yaml │ │ │ │ ├── ComplexCallbackResource.yaml │ │ │ │ ├── MultipleCallbacksTestWithOperationResource.yaml │ │ │ │ ├── RepeatableCallbackResource.yaml │ │ │ │ └── SimpleCallbackWithOperationResource.yaml │ │ │ ├── example/ │ │ │ │ └── ExamplesResource.yaml │ │ │ ├── links/ │ │ │ │ ├── LinksAndContent31Resource.yaml │ │ │ │ └── LinksResource.yaml │ │ │ ├── operation/ │ │ │ │ ├── AnnotatedSameNameOperationResource.yaml │ │ │ │ ├── ExternalDocumentationResource.yaml │ │ │ │ ├── FullyAnnotatedOperationResource.yaml │ │ │ │ ├── HiddenOperationResource.yaml │ │ │ │ ├── NotAnnotatedSameNameOperationResource.yaml │ │ │ │ ├── OperationResource.yaml │ │ │ │ ├── OperationWithoutAnnotationResource.yaml │ │ │ │ ├── ServerOperationResource.yaml │ │ │ │ └── SubResource.yaml │ │ │ ├── parameters/ │ │ │ │ ├── ArraySchemaResource.yaml │ │ │ │ ├── ComplexParameterResource.yaml │ │ │ │ ├── ComplexParameterWithOperationResource.yaml │ │ │ │ ├── MultipleNotAnnotatedParameter.yaml │ │ │ │ ├── OpenAPIJaxRSAnnotatedParameter.yaml │ │ │ │ ├── OpenAPIWithContentJaxRSAnnotatedParameter.yaml │ │ │ │ ├── OpenAPIWithImplementationJaxRSAnnotatedParameter.yaml │ │ │ │ ├── Parameters31Resource.yaml │ │ │ │ ├── ParametersResource.yaml │ │ │ │ ├── RepeatableParametersResource.yaml │ │ │ │ ├── SingleJaxRSAnnotatedParameter.yaml │ │ │ │ └── SingleNotAnnotatedParameter.yaml │ │ │ ├── requestbody/ │ │ │ │ ├── RequestBody31Resource.yaml │ │ │ │ ├── RequestBodyMethodPriorityResource.yaml │ │ │ │ ├── RequestBodyParameterPriorityResource.yaml │ │ │ │ └── RequestBodyResource.yaml │ │ │ ├── responses/ │ │ │ │ ├── ComplexResponseResource.yaml │ │ │ │ ├── ImplementationResponseResource.yaml │ │ │ │ ├── MethodArrayResponseResource.yaml │ │ │ │ ├── MethodResponseResource.yaml │ │ │ │ ├── NoImplementationResponseResource.yaml │ │ │ │ ├── NoResponseResource.yaml │ │ │ │ ├── OperationResponseResource.yaml │ │ │ │ └── PriorityResponseResource.yaml │ │ │ └── tags/ │ │ │ ├── CompleteTagResource.yaml │ │ │ ├── TagClassResource.yaml │ │ │ ├── TagMethodResource.yaml │ │ │ ├── TagOpenAPIDefinitionResource.yaml │ │ │ └── TagOperationResource.yaml │ │ └── webapp/ │ │ └── WEB-INF/ │ │ └── web.xml │ ├── swagger-jaxrs2-servlet-initializer/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── io/ │ │ │ └── swagger/ │ │ │ └── v3/ │ │ │ └── jaxrs2/ │ │ │ └── integration/ │ │ │ └── SwaggerServletInitializer.java │ │ └── resources/ │ │ └── META-INF/ │ │ └── services/ │ │ └── javax.servlet.ServletContainerInitializer │ ├── swagger-jaxrs2-servlet-initializer-v2/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── io/ │ │ │ └── swagger/ │ │ │ └── v3/ │ │ │ └── jaxrs2/ │ │ │ └── integration/ │ │ │ └── servlet/ │ │ │ └── SwaggerServletInitializer.java │ │ └── resources/ │ │ └── META-INF/ │ │ └── services/ │ │ └── javax.servlet.ServletContainerInitializer │ ├── swagger-maven-plugin/ │ │ ├── README.md │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── io/ │ │ │ └── swagger/ │ │ │ └── v3/ │ │ │ └── plugin/ │ │ │ └── maven/ │ │ │ ├── IncludeProjectDependenciesComponentConfigurator.java │ │ │ └── SwaggerMojo.java │ │ └── test/ │ │ ├── java/ │ │ │ └── io/ │ │ │ └── swagger/ │ │ │ └── v3/ │ │ │ └── plugin/ │ │ │ └── maven/ │ │ │ ├── ASwaggerMavenIntegrationTest.java │ │ │ ├── BetterAbstractMojoTestCase.java │ │ │ ├── SwaggerConfigFileTest.java │ │ │ ├── SwaggerResolveTest.java │ │ │ ├── petstore/ │ │ │ │ ├── petstore/ │ │ │ │ │ ├── EmptyPetResource.java │ │ │ │ │ ├── PetResource.java │ │ │ │ │ ├── callback/ │ │ │ │ │ │ ├── ComplexCallbackResource.java │ │ │ │ │ │ ├── MultipleCallbacksTestWithOperationResource.java │ │ │ │ │ │ ├── RepeatableCallbackResource.java │ │ │ │ │ │ └── SimpleCallbackWithOperationResource.java │ │ │ │ │ ├── example/ │ │ │ │ │ │ ├── ExamplesResource.java │ │ │ │ │ │ └── SubscriptionResponse.java │ │ │ │ │ ├── link/ │ │ │ │ │ │ └── LinksResource.java │ │ │ │ │ ├── openapidefintion/ │ │ │ │ │ │ └── OpenAPIDefinitionResource.java │ │ │ │ │ ├── operation/ │ │ │ │ │ │ ├── AnnotatedSameNameOperationResource.java │ │ │ │ │ │ ├── ExternalDocumentationResource.java │ │ │ │ │ │ ├── FullyAnnotatedOperationResource.java │ │ │ │ │ │ ├── HiddenOperationResource.java │ │ │ │ │ │ ├── InterfaceResource.java │ │ │ │ │ │ ├── NotAnnotatedSameNameOperationResource.java │ │ │ │ │ │ ├── OperationResource.java │ │ │ │ │ │ ├── OperationWithoutAnnotationResource.java │ │ │ │ │ │ ├── ServerOperationResource.java │ │ │ │ │ │ └── SubResource.java │ │ │ │ │ ├── parameter/ │ │ │ │ │ │ ├── ArraySchemaResource.java │ │ │ │ │ │ ├── ComplexParameterResource.java │ │ │ │ │ │ ├── ComplexParameterWithOperationResource.java │ │ │ │ │ │ ├── MultipleNotAnnotatedParameter.java │ │ │ │ │ │ ├── OpenAPIJaxRSAnnotatedParameter.java │ │ │ │ │ │ ├── OpenAPIWithContentJaxRSAnnotatedParameter.java │ │ │ │ │ │ ├── OpenAPIWithImplementationJaxRSAnnotatedParameter.java │ │ │ │ │ │ ├── ParametersResource.java │ │ │ │ │ │ ├── RepeatableParametersResource.java │ │ │ │ │ │ ├── SingleJaxRSAnnotatedParameter.java │ │ │ │ │ │ └── SingleNotAnnotatedParameter.java │ │ │ │ │ ├── requestbody/ │ │ │ │ │ │ ├── RequestBodyMethodPriorityResource.java │ │ │ │ │ │ ├── RequestBodyParameterPriorityResource.java │ │ │ │ │ │ └── RequestBodyResource.java │ │ │ │ │ ├── responses/ │ │ │ │ │ │ ├── ComplexResponseResource.java │ │ │ │ │ │ ├── ImplementationResponseResource.java │ │ │ │ │ │ ├── MethodResponseResource.java │ │ │ │ │ │ ├── NoImplementationResponseResource.java │ │ │ │ │ │ ├── NoResponseResource.java │ │ │ │ │ │ ├── OperationResponseResource.java │ │ │ │ │ │ └── PriorityResponseResource.java │ │ │ │ │ ├── security/ │ │ │ │ │ │ └── SecurityResource.java │ │ │ │ │ └── tags/ │ │ │ │ │ ├── CompleteTagResource.java │ │ │ │ │ ├── TagClassResource.java │ │ │ │ │ ├── TagMethodResource.java │ │ │ │ │ ├── TagOpenAPIDefinitionResource.java │ │ │ │ │ └── TagOperationResource.java │ │ │ │ └── petstore31/ │ │ │ │ └── PetResource.java │ │ │ └── resources/ │ │ │ ├── MyFilter.java │ │ │ ├── QueryResultBean.java │ │ │ ├── data/ │ │ │ │ ├── PetData.java │ │ │ │ └── UserData.java │ │ │ ├── exception/ │ │ │ │ ├── ApiException.java │ │ │ │ └── NotFoundException.java │ │ │ └── model/ │ │ │ ├── Category.java │ │ │ ├── CustomGenerator.java │ │ │ ├── ExtensionUser.java │ │ │ ├── JacksonBean.java │ │ │ ├── ListOfStringsBeanParam.java │ │ │ ├── ModelWithJsonIdentity.java │ │ │ ├── ModelWithJsonIdentityCyclic.java │ │ │ ├── MultipleBaseBean.java │ │ │ ├── MultipleSub1Bean.java │ │ │ ├── MultipleSub2Bean.java │ │ │ ├── NotFoundModel.java │ │ │ ├── Pet.java │ │ │ ├── Tag.java │ │ │ └── User.java │ │ └── resources/ │ │ ├── configurationFile.yaml │ │ ├── configurationFile2.yaml │ │ ├── logback-test.xml │ │ ├── openapiinput.json │ │ ├── openapiinput.yaml │ │ ├── openapiinput2.yaml │ │ ├── pom.resolveToFile.xml │ │ ├── pom.resolveToFile31.xml │ │ ├── pom.resolveToFileFromConfig.xml │ │ ├── pom.resolveToFileFromConfigAndOpenApi.xml │ │ ├── pom.resolveToFileFromConfigWithOAS3.1Filter.xml │ │ ├── pom.resolveToFileFromJsonInput.xml │ │ ├── pom.resolveToFileJsonAndYaml.xml │ │ ├── pom.resolveToFileNoName.xml │ │ └── pom.resolveToFileWithFilter.xml │ ├── swagger-models/ │ │ ├── CODE_COVERAGE.md │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── io/ │ │ │ └── swagger/ │ │ │ └── v3/ │ │ │ └── oas/ │ │ │ └── models/ │ │ │ ├── Components.java │ │ │ ├── ExternalDocumentation.java │ │ │ ├── OpenAPI.java │ │ │ ├── Operation.java │ │ │ ├── PathItem.java │ │ │ ├── Paths.java │ │ │ ├── SpecVersion.java │ │ │ ├── annotations/ │ │ │ │ ├── OpenAPI30.java │ │ │ │ └── OpenAPI31.java │ │ │ ├── callbacks/ │ │ │ │ └── Callback.java │ │ │ ├── examples/ │ │ │ │ └── Example.java │ │ │ ├── headers/ │ │ │ │ └── Header.java │ │ │ ├── info/ │ │ │ │ ├── Contact.java │ │ │ │ ├── Info.java │ │ │ │ └── License.java │ │ │ ├── links/ │ │ │ │ ├── Link.java │ │ │ │ └── LinkParameter.java │ │ │ ├── media/ │ │ │ │ ├── ArbitrarySchema.java │ │ │ │ ├── ArraySchema.java │ │ │ │ ├── BinarySchema.java │ │ │ │ ├── BooleanSchema.java │ │ │ │ ├── ByteArraySchema.java │ │ │ │ ├── ComposedSchema.java │ │ │ │ ├── Content.java │ │ │ │ ├── DateSchema.java │ │ │ │ ├── DateTimeSchema.java │ │ │ │ ├── Discriminator.java │ │ │ │ ├── EmailSchema.java │ │ │ │ ├── Encoding.java │ │ │ │ ├── EncodingProperty.java │ │ │ │ ├── FileSchema.java │ │ │ │ ├── IntegerSchema.java │ │ │ │ ├── JsonSchema.java │ │ │ │ ├── MapSchema.java │ │ │ │ ├── MediaType.java │ │ │ │ ├── NumberSchema.java │ │ │ │ ├── ObjectSchema.java │ │ │ │ ├── PasswordSchema.java │ │ │ │ ├── Schema.java │ │ │ │ ├── StringSchema.java │ │ │ │ ├── UUIDSchema.java │ │ │ │ └── XML.java │ │ │ ├── parameters/ │ │ │ │ ├── CookieParameter.java │ │ │ │ ├── HeaderParameter.java │ │ │ │ ├── Parameter.java │ │ │ │ ├── PathParameter.java │ │ │ │ ├── QueryParameter.java │ │ │ │ └── RequestBody.java │ │ │ ├── responses/ │ │ │ │ ├── ApiResponse.java │ │ │ │ └── ApiResponses.java │ │ │ ├── security/ │ │ │ │ ├── OAuthFlow.java │ │ │ │ ├── OAuthFlows.java │ │ │ │ ├── Scopes.java │ │ │ │ ├── SecurityRequirement.java │ │ │ │ └── SecurityScheme.java │ │ │ ├── servers/ │ │ │ │ ├── Server.java │ │ │ │ ├── ServerVariable.java │ │ │ │ └── ServerVariables.java │ │ │ └── tags/ │ │ │ └── Tag.java │ │ └── test/ │ │ └── java/ │ │ └── io/ │ │ └── swagger/ │ │ ├── test/ │ │ │ ├── SchemaTests.java │ │ │ └── SimpleBuilderTest.java │ │ └── v3/ │ │ └── oas/ │ │ └── models/ │ │ ├── PathsTest.java │ │ ├── links/ │ │ │ └── LinkParameterTest.java │ │ └── media/ │ │ └── SchemaTest.java │ └── swagger-project-jakarta/ │ ├── .gitignore │ ├── modules/ │ │ ├── swagger-annotations-jakarta/ │ │ │ └── pom.xml │ │ ├── swagger-core-jakarta/ │ │ │ └── pom.xml │ │ ├── swagger-integration-jakarta/ │ │ │ └── pom.xml │ │ ├── swagger-jaxrs2-jakarta/ │ │ │ └── pom.xml │ │ ├── swagger-jaxrs2-servlet-initializer-jakarta/ │ │ │ └── pom.xml │ │ ├── swagger-jaxrs2-servlet-initializer-v2-jakarta/ │ │ │ └── pom.xml │ │ ├── swagger-maven-plugin-jakarta/ │ │ │ ├── pom.xml │ │ │ ├── src/ │ │ │ │ └── main/ │ │ │ │ └── java/ │ │ │ │ └── io/ │ │ │ │ └── swagger/ │ │ │ │ └── v3/ │ │ │ │ └── plugin/ │ │ │ │ └── maven/ │ │ │ │ └── jakarta/ │ │ │ │ └── JakartaTransformer.java │ │ │ └── transformed/ │ │ │ └── README.md │ │ └── swagger-models-jakarta/ │ │ └── pom.xml │ └── pom.xml ├── mvnw ├── mvnw.cmd └── pom.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE/01_bug_report.md ================================================ --- name: Bug Report about: Report an issue in swagger-core title: "[Bug]: " labels: Bug assignees: '' --- ## Description of the problem/issue ## Affected Version e.g. 2.2.21 Earliest version the bug appears in (if known): e.g. 2.2.17 ## Steps to Reproduce 1. ... 2. ... 3. ... ## Expected Behavior ## Actual Behavior ## Logs / Stack Traces ## Additional Context ## Checklist - [ ] I have searched the [existing issues](https://github.com/swagger-api/swagger-core/issues) and this is not a duplicate. - [ ] I have provided sufficient information for maintainers to reproduce the issue. ================================================ FILE: .github/ISSUE_TEMPLATE/02_question.md ================================================ --- name: Question about: Ask a question about swagger-core usage or behavior title: "[Question]: " labels: Question assignees: '' --- ## Question ## Affected Version e.g. 2.2.21 ## Context ```java // Example code snippet here ``` ## Additional Details ## Checklist - [ ] I have searched the [existing issues](https://github.com/swagger-api/swagger-core/issues) and documentation before asking. - [ ] I have provided enough information for others to understand my question. ================================================ FILE: .github/ISSUE_TEMPLATE/03_feature_request.md ================================================ --- name: Feature Request about: Suggest a new feature or enhancement for swagger-core title: "[Feature]: " labels: Feature assignees: '' --- ## Feature Description ## Use Case ## Suggested Solution (optional) ## Alternatives Considered ## Additional Context ## Checklist - [ ] I have searched the [existing issues](https://github.com/swagger-api/swagger-core/issues) to ensure this is not a duplicate. - [ ] This feature would be useful to more than just my use case. - [ ] I have provided enough detail for the maintainers to understand the scope of the request. ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "maven" target-branch: "master" directory: "/" schedule: interval: "daily" ignore: - dependency-name: "*" update-types: ["version-update:semver-major"] - package-ecosystem: "maven" target-branch: "1.5" directory: "/" schedule: interval: "daily" ignore: - dependency-name: "*" update-types: ["version-update:semver-major"] ================================================ FILE: .github/pull_request_template.md ================================================ # Pull Request Thank you for contributing to **swagger-core**! Please fill out the following information to help us review your PR efficiently. --- ## Description Fixes: ## Type of Change - [ ] 🐛 Bug fix - [ ] ✨ New feature - [ ] ♻️ Refactor (non-breaking change) - [ ] 🧪 Tests - [ ] 📝 Documentation - [ ] 🧹 Chore (build or tooling) ## Checklist - [ ] I have added/updated tests as needed - [ ] I have added/updated documentation where applicable - [ ] The PR title is descriptive - [ ] The code builds and passes tests locally - [ ] I have linked related issues (if any) ## Screenshots / Additional Context ================================================ FILE: .github/topissuebot.yml ================================================ labelName: ":thumbsup: Top Issue!" labelColor: "f442c2" numberOfIssuesToLabel: 5 ================================================ FILE: .github/workflows/codeql-analysis.yml ================================================ name: "Code scanning - action" on: push: branches: [master, 1.5] pull_request: # The branches below must be a subset of the branches above branches: [master, 1.5] schedule: - cron: '0 19 * * 1' jobs: CodeQL-Build: runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false steps: - name: Checkout repository uses: actions/checkout@v4 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. fetch-depth: 2 # If this run was triggered by a pull request event, then checkout # the head of the pull request instead of the merge commit. - run: git checkout HEAD^2 if: ${{ github.event_name == 'pull_request' }} - name: Set up Java uses: actions/setup-java@v1 with: java-version: 11 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 # Override language selection by uncommenting this and choosing your languages with: languages: java - name: Cache local Maven repository uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Build with Maven and Gradle run: | ./mvnw --no-transfer-progress -B install --file pom.xml cd ./modules/swagger-gradle-plugin ./gradlew build --info cd ../.. - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 ================================================ FILE: .github/workflows/dependency-review.yml ================================================ name: 'Dependency Review' on: [pull_request] permissions: contents: read jobs: dependency-review: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' uses: actions/checkout@v4 - name: Dependency Review uses: actions/dependency-review-action@v3 with: fail-on-severity: high ================================================ FILE: .github/workflows/maven-pulls.yml ================================================ name: Build Test PR on: pull_request: branches: [ "master" ] jobs: build: runs-on: ubuntu-latest strategy: matrix: java: [ 11, 17 ] steps: - uses: actions/checkout@v4 - name: Set up Java uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} distribution: temurin server-id: central server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD - name: Cache local Maven repository uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Build with Maven and Gradle run: | ./mvnw --no-transfer-progress -B install --file pom.xml cd ./modules/swagger-gradle-plugin ./gradlew build --info cd ../.. ================================================ FILE: .github/workflows/maven-v1-pulls.yml ================================================ name: Build Test PR 1.5 on: pull_request: branches: [ "1.5" ] jobs: build: runs-on: ubuntu-latest strategy: matrix: java: [ 11, 17 ] steps: - uses: actions/checkout@v2 - name: Set up Java uses: actions/setup-java@v1 with: java-version: ${{ matrix.java }} - name: Cache local Maven repository uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Build with Maven and Gradle run: ./mvnw -B -Dhttps.protocols=TLSv1.2 verify --file pom.xml ================================================ FILE: .github/workflows/maven-v1.yml ================================================ name: Build Test Deploy 1.5 on: push: branches: [ "1.5" ] jobs: build: runs-on: ubuntu-latest strategy: matrix: java: [ 11, 17 ] steps: - uses: actions/checkout@v2 - name: Set up Java uses: actions/setup-java@v1 with: java-version: ${{ matrix.java }} server-id: sonatype-nexus-snapshots server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD - name: Cache local Maven repository uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Build with Maven and Gradle run: | ./mvnw -B -Dhttps.protocols=TLSv1.2 verify --file pom.xml export MY_JAVA_VERSION=`java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1` echo "JAVA VERSION" ${MY_JAVA_VERSION} if [[ ${MY_JAVA_VERSION} == "11" ]]; then export MY_POM_VERSION=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` echo "POM VERSION" ${MY_POM_VERSION} if [[ $MY_POM_VERSION =~ ^.*SNAPSHOT$ ]]; then ./mvnw -B -Dhttps.protocols=TLSv1.2 clean deploy else echo "not deploying release: " ${MY_POM_VERSION} fi else echo "not deploying on java version: " ${MY_JAVA_VERSION} fi env: MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} ================================================ FILE: .github/workflows/maven.yml ================================================ name: Build Test Deploy master on: push: branches: [ "master" ] jobs: build: runs-on: ubuntu-latest strategy: matrix: java: [ 11, 17 ] steps: - uses: actions/checkout@v4 - name: Set up Java uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} distribution: temurin server-id: central server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD - name: Cache local Maven repository uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Build with Maven and Gradle, Deploy snapshot to maven central run: | export MY_POM_VERSION=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` echo "POM VERSION" ${MY_POM_VERSION} if [[ $MY_POM_VERSION =~ ^.*SNAPSHOT$ ]]; then ./mvnw --no-transfer-progress -B install --file pom.xml cd ./modules/swagger-gradle-plugin ./gradlew build --info cd ../.. export MY_JAVA_VERSION=`java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1` echo "JAVA VERSION" ${MY_JAVA_VERSION} if [[ ${MY_JAVA_VERSION} == "11" ]]; then export MY_POM_VERSION=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` echo "POM VERSION" ${MY_POM_VERSION} ./mvnw --no-transfer-progress -B clean deploy else echo "not deploying on java version: " ${MY_JAVA_VERSION} fi else echo "not building and maven publishing project as it is a release version: " ${MY_JAVA_VERSION} fi env: MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} ================================================ FILE: .github/workflows/prepare-release.yml ================================================ name: Prepare Release on: workflow_dispatch: branches: ["master"] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: tibdex/github-app-token@v1 id: generate-token with: app_id: ${{ secrets.APP_ID }} private_key: ${{ secrets.APP_PRIVATE_KEY }} - name: Set up Python 3.10 uses: actions/setup-python@v4 with: python-version: '3.10' - name: Set up Java 11 uses: actions/setup-java@v4 with: java-version: 11 distribution: temurin server-id: central server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD - name: Cache local Maven repository uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Run prepare release script id: prepare-release run: | export MY_POM_VERSION=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` if [[ $MY_POM_VERSION =~ ^.*SNAPSHOT$ ]]; then . ./CI/prepare-release.sh echo "PREPARE_RELEASE_OK=yes" >> $GITHUB_ENV else echo "not preparing release for release version: " ${MY_POM_VERSION} echo "PREPARE_RELEASE_OK=no" >> $GITHUB_ENV fi echo "SC_VERSION=$SC_VERSION" >> $GITHUB_ENV echo "SC_NEXT_VERSION=$SC_NEXT_VERSION" >> $GITHUB_ENV - name: Create Prepare Release Pull Request uses: peter-evans/create-pull-request@v4 if: env.PREPARE_RELEASE_OK == 'yes' with: token: ${{ steps.generate-token.outputs.token }} commit-message: prepare release ${{ env.SC_VERSION }} title: 'prepare release ${{ env.SC_VERSION }}' branch: prepare-release-${{ env.SC_VERSION }} env: ACTIONS_ALLOW_UNSECURE_COMMANDS: true MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} SC_VERSION: SC_NEXT_VERSION: ================================================ FILE: .github/workflows/release.yml ================================================ name: Release on: workflow_dispatch: branches: ["master"] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: tibdex/github-app-token@v1 id: generate-token with: app_id: ${{ secrets.APP_ID }} private_key: ${{ secrets.APP_PRIVATE_KEY }} - name: Set up Python 3.10 uses: actions/setup-python@v4 with: python-version: '3.10' - name: Set up Java 11 uses: actions/setup-java@v4 with: java-version: 11 distribution: temurin server-id: central server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD gpg-private-key: ${{ secrets.OSSRH_GPG_PRIVATE_KEY }} - name: Cache local Maven repository uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Set up Gradle credentials run: | mkdir -p ~/.gradle echo "gradle.publish.key=${GRADLE_PUBLISH_KEY}\ngradle.publish.secret=${GRADLE_PUBLISH_SECRET}" > ~/.gradle/gradle.properties - name: Run pre release script id: preRelease run: | # export GPG_TTY=$(tty) export MY_POM_VERSION=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` if [[ $MY_POM_VERSION =~ ^.*SNAPSHOT$ ]]; then echo "not releasing snapshot version: " ${MY_POM_VERSION} echo "RELEASE_OK=no" >> $GITHUB_ENV else . ./CI/pre-release.sh echo "RELEASE_OK=yes" >> $GITHUB_ENV fi echo "SC_VERSION=$SC_VERSION" >> $GITHUB_ENV echo "SC_NEXT_VERSION=$SC_NEXT_VERSION" >> $GITHUB_ENV echo "SC_LAST_RELEASE=$SC_LAST_RELEASE" >> $GITHUB_ENV - name: configure git user email run: | git config --global user.email "action@github.com" git config --global user.name "GitHub Action" git config --global hub.protocol https git remote set-url origin https://\${{ secrets.GITHUB_TOKEN }}:x-oauth-basic@github.com/''' + 'swagger-api/swagger-core' + '''.git - name: Run maven deploy/release if: env.RELEASE_OK == 'yes' run: | ./mvnw --no-transfer-progress -B -Prelease deploy - name: Run prepare javadocs script id: prepareJavadocs if: env.RELEASE_OK == 'yes' run: | . ./CI/prepare-javadocs.sh - name: Checkout gh-pages uses: actions/checkout@v4 with: ref: "gh-pages" fetch-depth: 0 - name: Run publish javadocs script id: publishJavadocs if: env.RELEASE_OK == 'yes' run: | TMPDIR="$(dirname -- "${0}")" . $TMPDIR/publish-javadocs.sh - name: Checkout master uses: actions/checkout@v4 with: ref: "master" fetch-depth: 0 - name: Run post release script id: postRelease if: env.RELEASE_OK == 'yes' run: | . ./CI/post-release.sh - name: Create Next Snapshot Pull Request uses: peter-evans/create-pull-request@v4 if: env.RELEASE_OK == 'yes' with: token: ${{ steps.generate-token.outputs.token }} commit-message: bump snapshot ${{ env.SC_NEXT_VERSION }}-SNAPSHOT title: 'bump snapshot ${{ env.SC_NEXT_VERSION }}-SNAPSHOT' branch: bump-snap-${{ env.SC_NEXT_VERSION }}-SNAPSHOT - name: Checkout 1.5 uses: actions/checkout@v4 with: ref: "1.5" fetch-depth: 0 - name: updateV1Readme script id: updateV1Readme if: env.RELEASE_OK == 'yes' run: | TMPDIR="$(dirname -- "${0}")" . $TMPDIR/update-v1-readme.sh ${{ env.SC_LAST_RELEASE }} ${{ env.SC_VERSION }} - name: Create Update V1 Readme Pull Request uses: peter-evans/create-pull-request@v4 if: env.RELEASE_OK == 'yes' with: token: ${{ steps.generate-token.outputs.token }} commit-message: update 1.5 Readme with new v2 version ${{ env.SC_VERSION }} title: 'update 1.5 Readme with new v2 version ${{ env.SC_VERSION }}' branch: update-v1-readme-${{ env.SC_VERSION }} - name: Checkout Wiki uses: actions/checkout@v4 with: repository: swagger-api/swagger-core.wiki token: ${{ steps.generate-token.outputs.token }} path: wiki ref: "master" fetch-depth: 0 - name: Run update wiki script id: updateWiki if: env.RELEASE_OK == 'yes' run: | TMPDIR="$(dirname -- "${0}")" . $TMPDIR/update-wiki.sh - name: Checkout master uses: actions/checkout@v2 with: ref: "master" fetch-depth: 0 env: ACTIONS_ALLOW_UNSECURE_COMMANDS: true MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} SC_VERSION: SC_NEXT_VERSION: GPG_PRIVATE_KEY: ${{ secrets.OSSRH_GPG_PRIVATE_KEY }} GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_PRIVATE_PASSPHRASE }} GRADLE_PUBLISH_KEY: ${{ secrets.GRADLE_PUBLISH_KEY }} GRADLE_PUBLISH_SECRET: ${{ secrets.GRADLE_PUBLISH_SECRET }} ================================================ FILE: .gitignore ================================================ build/ lib/*.jar target samples/scala-play2/logs .idea .idea_modules .settings .project .classpath .cache atlassian-ide-plugin.xml *.iml .java-version sonar-project.properties test-output/ *.pyc ================================================ FILE: .mvn/wrapper/maven-wrapper.properties ================================================ # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar ================================================ FILE: .whitesource ================================================ { "settingsInheritedFrom": "swagger-api/whitesource-config@main", "scanSettings": { "baseBranches": ["master", "1.5"] } } ================================================ FILE: CI/CI.md ================================================ ## Continuous integration ### Build, test and deploy Swagger Core uses Github actions to run jobs/checks building, testing and deploying snapshots on push and PR events. These github actions are configured in `.github/workflows`: * maven.yml : Build Test Deploy master * maven-pulls.yml Build Test PR * maven-v1.yml : Build Test Deploy 1.5 (must exist in in `1.5` branch) * maven-v1-pulls.yml Build Test PR 1.5 (must exist in in `1.5` branch) These actions use available actions in combination with short bash scripts. ### Release Releases are semi-automated and consist in 2 actions using available public actions in combination with bash and python scripts. **TODO**: Python code is used for historical reasons to execute GitHub APIs calls, in general a more consistent environment would be more maintainable e.g. implementing a custom JavaScript or Docker Container GitHub Action and/or a bash only script(s). #### Workflow summary 1. execute `prepare-release.yml` / `Prepare Release` for `master` branch 1. check and merge the Prepare Release PR pushed by previous step. Delete the branch 1. execute `release.yml` / `Release` for `master` branch 1. check and merge the `1.5` branch Readme update PR pushed by previous step. Delete the branch 1. check and merge the next snaphot PR pushed by previous step. Delete the branch #### Prepare Release The first action to execute is `prepare-release.yml` / `Prepare Release` for master, and `prepare-release-v1.yml` / `Prepare Release V1` for `1.5` branch. This is triggered by manually executing the action, selecting `Actions` in project GitHub UI, then `Prepare Release` workflow and clicking `Run Workflow` (or `Prepare Release V1` and selecting `1.5` in the dropdown) `Prepare Release` takes care of: * create release notes out of merged PRs * Draft a release with related tag * bump versions to release, and update all affected files * build and test maven * build and test gradle plugin * push a Pull Request with the changes for human check. After the PR checks complete, the PR can me merged, and the second phase `Release` started. #### Release Once prepare release PR has been merged, the second phase is provided by `release.yml` / `Release` actions for master, and `release-v1.yml` / `Release V1` for `1.5` branch. This is triggered by manually executing the action, selecting `Actions` in project GitHub UI, then `Release` workflow and clicking `Run Workflow` (or `Release V1` and selecting `1.5` in the dropdown) `Release` takes care of: * build and test maven * build and test gradle plugin * deploy/publish to maven central * publish javadocs to gh-pages * deploy/publish gradle plugin * publish the previously prepared GitHub release / tag * push PR for next snapshot * push PR for 1.5 Readme update with new v2 version * update Wiki with javadocs links to new version ### Secrets GitHub Actions make use of `Secrets` which can be configured either with Repo or Organization scope; the needed secrets are the following: * `APP_ID` and APP_PRIVATE_KEY`: these are the values provided by an account configured GitHub App, allowing to obtain a GitHub token different from the default used in GitHub Actions (which does not allow to "chain" actions).Actions The GitHub App must be configured as detailed in [this doc](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#authenticating-with-github-app-generated-tokens). See also [here](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#triggering-further-workflow-runs) * `OSSRH_GPG_PRIVATE_KEY` and `OSSRH_GPG_PRIVATE_PASSPHRASE` : gpg key and passphrase to be used for sonatype releases GPG private key and passphrase defined to be used for sonatype deployments, as detailed in https://central.sonatype.org/pages/working-with-pgp-signatures.html (I'd say with email matching the one of the sonatype account of point 1 * `MAVEN_CENTRAL_USERNAME` and `MAVEN_CENTRAL_PASSWORD`: sonatype user/token * `GRADLE_PUBLISH_KEY` and `GRADLE_PUBLISH_SECRET`: credentials for https://plugins.gradle.org/ ================================================ FILE: CI/ghApiClient.py ================================================ #!/usr/bin/python import os import time import urllib.request, urllib.error, urllib.parse import http.client import json GH_BASE_URL = "https://api.github.com/" GH_TOKEN = os.environ['GH_TOKEN'] GH_AUTH = "Bearer %s" % GH_TOKEN def readUrl(name): try: request = urllib.request.Request(GH_BASE_URL + name) request.add_header("Authorization", GH_AUTH) content = urllib.request.urlopen(request).read() jcont = json.loads(content) return jcont except urllib.error.HTTPError as e: print(('HTTPError = ' + str(e.code))) raise e except urllib.error.URLError as e: print(('URLError = ' + str(e.reason))) raise e except http.client.HTTPException as e: print(('HTTPException = ' + str(e))) raise e except Exception: import traceback print(('generic exception: ' + traceback.format_exc())) raise IOError def postUrl(name, body): global GH_BASE_URL try: time.sleep(0.05) request = urllib.request.Request(GH_BASE_URL + name) request.add_header("Authorization", GH_AUTH) request.add_header("Accept", "application/vnd.github.v3+json") data = body.encode('utf-8') content = urllib.request.urlopen(request, data).read() jcont = json.loads(content) return jcont except urllib.error.HTTPError as e: print(('HTTPError = ' + str(e.code))) print((str(e))) raise e except urllib.error.URLError as e: print(('URLError = ' + str(e.reason))) raise e except http.client.HTTPException as e: print(('HTTPException = ' + str(e))) raise e except Exception: import traceback print(('generic exception: ' + traceback.format_exc())) raise IOError ================================================ FILE: CI/lastRelease.py ================================================ #!/usr/bin/python import ghApiClient def getLastReleaseTag(): content = ghApiClient.readUrl('repos/swagger-api/swagger-core/releases') for l in content: draft = l["draft"] tag = l["tag_name"] if str(draft) != 'True' and tag.startswith("v2"): return tag[1:] # main def main(): result = getLastReleaseTag() print (result) # here start main main() ================================================ FILE: CI/post-release.sh ================================================ #!/bin/bash CUR=$(pwd) TMPDIR="$(dirname -- "${0}")" SC_RELEASE_TAG="v$SC_VERSION" ##################### ### deploy gradle plugin release ##################### cd modules/swagger-gradle-plugin ./gradlew publishPlugins -Pgradle.publish.key="${GRADLE_PUBLISH_KEY}" -Pgradle.publish.secret="${GRADLE_PUBLISH_SECRET}" --info cd ../.. ##################### ### publish pre-prepared release (tag is created) ##################### python $CUR/CI/publishRelease.py "$SC_RELEASE_TAG" ##################### ### update the version to next snapshot in maven project with set version ##################### ./mvnw versions:set -DnewVersion="${SC_NEXT_VERSION}-SNAPSHOT" ./mvnw versions:commit cd modules/swagger-project-jakarta ../../mvnw versions:set -DnewVersion="${SC_NEXT_VERSION}-SNAPSHOT" ../../mvnw versions:commit cd ../.. ##################### ### update all other versions in files around to the next snapshot or new release, including readme and gradle ### ##################### sc_find="version=$SC_VERSION" sc_replace="version=$SC_NEXT_VERSION-SNAPSHOT" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-gradle-plugin/gradle.properties sc_find="io.swagger.core.v3:swagger-jaxrs2:$SC_VERSION" sc_replace="io.swagger.core.v3:swagger-jaxrs2:$SC_NEXT_VERSION-SNAPSHOT" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java sc_find="io.swagger.core.v3:swagger-jaxrs2:$SC_VERSION" sc_replace="io.swagger.core.v3:swagger-jaxrs2:$SC_NEXT_VERSION-SNAPSHOT" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java sc_find="$SC_VERSION<\/version>" sc_replace="$SC_NEXT_VERSION-SNAPSHOT<\/version>" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-java17-support/pom.xml rm -f $CUR/modules/swagger-java17-support/pom.xml.versionsBackup ##################### ### Copy scripts to temp folder, as they are not available when checking out different branch or repo ##################### cp -a $CUR/CI/update-v1-readme.sh $TMPDIR/update-v1-readme.sh cp -a $CUR/CI/update-wiki.sh $TMPDIR/update-wiki.sh ================================================ FILE: CI/pre-release.sh ================================================ #!/bin/bash CUR=$(pwd) export SC_VERSION=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}' --non-recursive build-helper:parse-version org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` export SC_NEXT_VERSION=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion}' --non-recursive build-helper:parse-version org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` SC_QUALIFIER=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${parsedVersion.qualifier}' --non-recursive build-helper:parse-version org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` #SC_LAST_RELEASE=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${releasedVersion.version}' --non-recursive org.codehaus.mojo:build-helper-maven-plugin:3.2.0:released-version org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` SC_LAST_RELEASE=`python $CUR/CI/lastRelease.py` SC_RELEASE_TAG="v$SC_VERSION" ##################### ### build and test maven ### ##################### ./mvnw --no-transfer-progress -B install --file pom.xml ##################### ### build and test gradle ### ##################### cd ./modules/swagger-gradle-plugin ./gradlew build --info cd ../.. ================================================ FILE: CI/prepare-javadocs.sh ================================================ #!/bin/bash CUR=$(pwd) TMPDIR="$(dirname -- "${0}")" SC_RELEASE_TAG="v$SC_VERSION" ##################### ### publish javadocs ##################### cp -aR $CUR/modules/swagger-annotations/target/javadocprep/swagger-core/${SC_VERSION}/apidocs $TMPDIR cp -a $CUR/CI/publish-javadocs.sh $TMPDIR/publish-javadocs.sh ================================================ FILE: CI/prepare-release.sh ================================================ #!/bin/bash CUR=$(pwd) export SC_VERSION=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}' --non-recursive build-helper:parse-version org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` export SC_NEXT_VERSION=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion}' --non-recursive build-helper:parse-version org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` SC_QUALIFIER=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${parsedVersion.qualifier}' --non-recursive build-helper:parse-version org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` #SC_LAST_RELEASE=`./mvnw -q -Dexec.executable="echo" -Dexec.args='${releasedVersion.version}' --non-recursive org.codehaus.mojo:build-helper-maven-plugin:3.2.0:released-version org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` SC_LAST_RELEASE=`python $CUR/CI/lastRelease.py` SC_RELEASE_TITLE="Swagger-core $SC_VERSION released!" SC_RELEASE_TAG="v$SC_VERSION" ##################### ### draft release Notes with next release after last release, with tag ##################### python $CUR/CI/releaseNotes.py "$SC_LAST_RELEASE" "$SC_RELEASE_TITLE" "$SC_RELEASE_TAG" ##################### ### update the version to release in maven project with set version ##################### ./mvnw versions:set -DnewVersion=$SC_VERSION ./mvnw versions:commit cd modules/swagger-project-jakarta ../../mvnw versions:set -DnewVersion=$SC_VERSION ../../mvnw versions:commit cd ../.. ##################### ### update all other versions in files around to the new release, including readme and gradle ### ##################### sc_find="currently $SC_VERSION-SNAPSHOT" sc_replace="currently $SC_NEXT_VERSION-SNAPSHOT" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/README.md sc_find="$SC_LAST_RELEASE (\*\*current stable\*\*)" sc_replace="$SC_LAST_RELEASE " sed -i -e "s/$sc_find/$sc_replace/g" $CUR/README.md # update readme with a line for the new release replacing the previous CURDATE=$(date +"%Y-%m-%d") sc_find="------------------------- | ------------ | -------------------------- | ----- | ----" sc_add="$SC_VERSION (**current stable**)| $CURDATE | 3.x | [tag v$SC_VERSION](https:\/\/github.com\/swagger-api\/swagger-core\/tree\/v$SC_VERSION) | Supported" sc_replace="$sc_find\n$sc_add" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/README.md sc_find="\"io.swagger.core.v3.swagger-gradle-plugin\" version \"$SC_LAST_RELEASE\"" sc_replace="\"io.swagger.core.v3.swagger-gradle-plugin\" version \"$SC_VERSION\"" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-gradle-plugin/README.md sc_find="classpath \"io.swagger.core.v3:swagger-gradle-plugin:$SC_LAST_RELEASE\"" sc_replace="classpath \"io.swagger.core.v3:swagger-gradle-plugin:$SC_VERSION\"" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-gradle-plugin/README.md sc_find="version=$SC_VERSION\-SNAPSHOT" sc_replace="version=$SC_VERSION" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-gradle-plugin/gradle.properties sc_find="io.swagger.core.v3:swagger-jaxrs2:$SC_VERSION-SNAPSHOT" sc_replace="io.swagger.core.v3:swagger-jaxrs2:$SC_VERSION" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java sc_find="io.swagger.core.v3:swagger-jaxrs2:$SC_VERSION-SNAPSHOT" sc_replace="io.swagger.core.v3:swagger-jaxrs2:$SC_VERSION" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java sc_find="$SC_LAST_RELEASE<\/version>" sc_replace="$SC_VERSION<\/version>" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-maven-plugin/README.md sc_find="$SC_LAST_RELEASE<\/version>" sc_replace="$SC_VERSION<\/version>" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/modules/swagger-java17-support/pom.xml rm -f $CUR/modules/swagger-java17-support/pom.xml.versionsBackup ##################### ### build and test maven ### ##################### ./mvnw --no-transfer-progress -B install --file pom.xml ##################### ### build and test gradle ### ##################### cd ./modules/swagger-gradle-plugin ./gradlew build --info cd ../.. ================================================ FILE: CI/publish-javadocs.sh ================================================ #!/bin/bash CUR=$(pwd) TMPDIR="$(dirname -- "${0}")" SC_RELEASE_TAG="v$SC_VERSION" ##################### ### publish javadocs ##################### mkdir -p $CUR/swagger-core/${SC_RELEASE_TAG} cp -aR $TMPDIR/apidocs $CUR/swagger-core/${SC_RELEASE_TAG} git add -A git commit -m "apidocs for release ${SC_RELEASE_TAG}" git push -u origin gh-pages ================================================ FILE: CI/publishRelease.py ================================================ #!/usr/bin/python import sys import ghApiClient def lastReleaseId(tag): content = ghApiClient.readUrl('repos/swagger-api/swagger-core/releases') for l in content: draft = l["draft"] draft_tag = l["tag_name"] if str(draft) == 'True' and tag == draft_tag: return l["id"] def publishRelease(tag): id = lastReleaseId(tag) payload = "{\"tag_name\":\"" + tag + "\", " payload += "\"draft\":" + "false" + ", " payload += "\"target_commitish\":\"" + "master" + "\"}" content = ghApiClient.postUrl('repos/swagger-api/swagger-core/releases/' + str(id), payload) return content # main def main(tag): publishRelease (tag) # here start main main(sys.argv[1]) ================================================ FILE: CI/releaseNotes.py ================================================ #!/usr/bin/python import sys import json from datetime import datetime import ghApiClient def allPulls(releaseDate): result = "" baseurl = "https://api.github.com/repos/swagger-api/swagger-core/pulls/" content = ghApiClient.readUrl('repos/swagger-api/swagger-core/pulls?state=closed&base=master&per_page=100') for l in content: stripped = l["url"][len(baseurl):] mergedAt = l["merged_at"] if mergedAt is not None: if datetime.strptime(mergedAt, '%Y-%m-%dT%H:%M:%SZ') > releaseDate: if not l['title'].startswith("bump snap"): result += '\n' result += "* " + l['title'] + " (#" + stripped + ")" return result def lastReleaseDate(tag): content = ghApiClient.readUrl('repos/swagger-api/swagger-core/releases/tags/' + tag) publishedAt = content["published_at"] return datetime.strptime(publishedAt, '%Y-%m-%dT%H:%M:%SZ') def addRelease(release_title, tag, content): payload = "{\"tag_name\":\"" + tag + "\", " payload += "\"name\":" + json.dumps(release_title) + ", " payload += "\"body\":" + json.dumps(content) + ", " payload += "\"draft\":" + "true" + ", " payload += "\"prerelease\":" + "false" + ", " payload += "\"target_commitish\":\"" + "master" + "\"}" content = ghApiClient.postUrl('repos/swagger-api/swagger-core/releases', payload) return content def getReleases(): content = ghApiClient.readUrl('repos/swagger-api/swagger-core/releases') return content # main def main(last_release, release_title, tag): result = allPulls(lastReleaseDate('v' + last_release)) addRelease (release_title, tag, result) # here start main main(sys.argv[1], sys.argv[2], sys.argv[3]) ================================================ FILE: CI/test.py ================================================ #!/usr/bin/python import sys import json from datetime import datetime import ghApiClient def allPulls(releaseDate): result = "" baseurl = "https://api.github.com/repos/swagger-api/swagger-core/pulls/" content = ghApiClient.readUrl('repos/swagger-api/swagger-core/pulls?state=closed&base=master&per_page=100') for l in content: stripped = l["url"][len(baseurl):] mergedAt = l["merged_at"] if mergedAt is not None: if datetime.strptime(mergedAt, '%Y-%m-%dT%H:%M:%SZ') > releaseDate: if not l['title'].startswith("bump snap"): result += '\n' result += "* " + l['title'] + " (#" + stripped + ")" return result def lastReleaseDate(tag): content = ghApiClient.readUrl('repos/swagger-api/swagger-core/releases/tags/' + tag) publishedAt = content["published_at"] return datetime.strptime(publishedAt, '%Y-%m-%dT%H:%M:%SZ') def addRelease(release_title, tag, content): payload = "{\"tag_name\":\"" + tag + "\", " payload += "\"name\":" + json.dumps(release_title) + ", " payload += "\"body\":" + json.dumps(content) + ", " payload += "\"draft\":" + "true" + ", " payload += "\"prerelease\":" + "false" + ", " payload += "\"target_commitish\":\"" + "master" + "\"}" content = ghApiClient.postUrl('repos/swagger-api/swagger-core/releases', payload) return content def getReleases(): content = ghApiClient.readUrl('repos/swagger-api/swagger-core/releases') return content # main def main(last_release, release_title, tag): baseurl = "https://api.github.com/repos/swagger-api/swagger-core/pulls/" payload = "{\"tag_name\":\"" + tag + "\", " payload += "\"name\":" + json.dumps(release_title) + ", " payload += "\"body\":" + json.dumps(content) + ", " payload += "\"draft\":" + "true" + ", " payload += "\"prerelease\":" + "false" + ", " payload += "\"target_commitish\":\"" + "master" + "\"}" content = ghApiClient.postUrl('repos/swagger-api/swagger-core/releases', payload) result = allPulls(lastReleaseDate('v' + last_release)) addRelease (release_title, tag, result) # here start main main(sys.argv[1], sys.argv[2], sys.argv[3]) ================================================ FILE: CI/update-v1-readme.sh ================================================ #!/bin/bash SC_LAST_RELEASE="$1" SC_VERSION="$2" CUR=$(pwd) ##################### ### update v2 versions in readme ##################### sc_find="$SC_LAST_RELEASE (\*\*current stable\*\*)" sc_replace="$SC_LAST_RELEASE " sed -i -e "s/$sc_find/$sc_replace/g" $CUR/README.md # update readme with a line for the new release replacing the previous CURDATE=$(date +"%Y-%m-%d") sc_find="------------------------- | ------------ | -------------------------- | ----- | ----" sc_add="$SC_VERSION (**current stable**)| $CURDATE | 3.x | [tag v$SC_VERSION](https:\/\/github.com\/swagger-api\/swagger-core\/tree\/v$SC_VERSION) | Supported" sc_replace="$sc_find\n$sc_add" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/README.md ================================================ FILE: CI/update-wiki.sh ================================================ #!/bin/bash CUR=$(pwd) ##################### ### update Wiki ##################### cd wiki sc_find="$SC_LAST_RELEASE\/" sc_replace="$SC_VERSION\/" sed -i -e "s/$sc_find/$sc_replace/g" $CUR/wiki/Swagger-2.X---Annotations.md git add -A git commit -m "update javadocs links to ${SC_VERSION}" git push -u origin master cd .. ================================================ 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 (c) 2015. SmartBear Software Inc. 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: NOTICE ================================================ Swagger Core - ${pom.name} Copyright (c) 2015. SmartBear Software Inc. Swagger Core - ${pom.name} is licensed under Apache 2.0 license. Copy of the Apache 2.0 license can be found in `LICENSE` file. ================================================ FILE: README.md ================================================ # Swagger Core **NOTE:** If you're looking for Swagger Core 1.5.X and OpenAPI 2.0, please refer to [1.5 branch](https://github.com/swagger-api/swagger-core/tree/1.5). **NOTE:** Since version 2.1.7, Swagger Core also supports the Jakarta namespace. There are a parallel set of artifacts with the `-jakarta` suffix, providing the same functionality as the unsuffixed (i.e.: `javax`) artifacts. Please see the [Wiki](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Getting-started) for more details. **NOTE:** Since version 2.2.0 Swagger Core supports OpenAPI 3.1; see [this page](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---OpenAPI-3.1) for details ![Build Test Deploy](https://github.com/swagger-api/swagger-core/workflows/Build%20Test%20Deploy%20master/badge.svg?branch=master) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.swagger.core.v3/swagger-project/badge.svg?style=plastic)](https://maven-badges.herokuapp.com/maven-central/io.swagger.core.v3/swagger-project) Swagger Core is a Java implementation of the OpenAPI Specification. Current version supports *JAX-RS2* (`javax` and `jakarta` namespaces). ## Get started with Swagger Core! See the guide on [getting started with Swagger Core](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Getting-started) to get started with adding Swagger to your API. ## See the Wiki! The [github wiki](https://github.com/swagger-api/swagger-core/wiki) contains documentation, samples, contributions, etc. Start there. ## Compatibility The OpenAPI Specification has undergone several revisions since initial creation in 2010. The Swagger Core project has the following compatibilities with the OpenAPI Specification: Swagger core Version | Release Date | OpenAPI Spec compatibility | Notes | Status ------------------------- | ------------ | -------------------------- | ----- | ---- 2.2.45 (**current stable**)| 2026-03-09 | 3.x | [tag v2.2.45](https://github.com/swagger-api/swagger-core/tree/v2.2.45) | Supported 2.2.44 | 2026-03-03 | 3.x | [tag v2.2.44](https://github.com/swagger-api/swagger-core/tree/v2.2.44) | Supported 2.2.43 | 2026-02-17 | 3.x | [tag v2.2.43](https://github.com/swagger-api/swagger-core/tree/v2.2.43) | Supported 2.2.42 | 2026-01-19 | 3.x | [tag v2.2.42](https://github.com/swagger-api/swagger-core/tree/v2.2.42) | Supported 2.2.41 | 2025-11-24 | 3.x | [tag v2.2.41](https://github.com/swagger-api/swagger-core/tree/v2.2.41) | Supported 2.2.40 | 2025-10-28 | 3.x | [tag v2.2.40](https://github.com/swagger-api/swagger-core/tree/v2.2.40) | Supported 2.2.39 | 2025-10-13 | 3.x | [tag v2.2.39](https://github.com/swagger-api/swagger-core/tree/v2.2.39) | Supported 2.2.38 | 2025-09-29 | 3.x | [tag v2.2.38](https://github.com/swagger-api/swagger-core/tree/v2.2.38) | Supported 2.2.37 | 2025-09-16 | 3.x | [tag v2.2.37](https://github.com/swagger-api/swagger-core/tree/v2.2.37) | Supported 2.2.36 | 2025-08-18 | 3.x | [tag v2.2.36](https://github.com/swagger-api/swagger-core/tree/v2.2.36) | Supported 2.2.35 | 2025-07-31 | 3.x | [tag v2.2.35](https://github.com/swagger-api/swagger-core/tree/v2.2.35) | Supported 2.2.34 | 2025-06-20 | 3.x | [tag v2.2.34](https://github.com/swagger-api/swagger-core/tree/v2.2.34) | Supported 2.2.33 | 2025-06-12 | 3.x | [tag v2.2.33](https://github.com/swagger-api/swagger-core/tree/v2.2.33) | Supported 2.2.32 | 2025-05-14 | 3.x | [tag v2.2.32](https://github.com/swagger-api/swagger-core/tree/v2.2.32) | Supported 2.2.31 | 2025-05-13 | 3.x | [tag v2.2.31](https://github.com/swagger-api/swagger-core/tree/v2.2.31) | Supported 2.2.30 | 2025-04-07 | 3.x | [tag v2.2.30](https://github.com/swagger-api/swagger-core/tree/v2.2.30) | Supported 2.2.29 | 2025-03-10 | 3.x | [tag v2.2.29](https://github.com/swagger-api/swagger-core/tree/v2.2.29) | Supported 2.2.28 | 2025-01-16 | 3.x | [tag v2.2.28](https://github.com/swagger-api/swagger-core/tree/v2.2.28) | Supported 2.2.27 | 2024-12-11 | 3.x | [tag v2.2.27](https://github.com/swagger-api/swagger-core/tree/v2.2.27) | Supported 2.2.26 | 2024-11-18 | 3.x | [tag v2.2.26](https://github.com/swagger-api/swagger-core/tree/v2.2.26) | Supported 2.2.25 | 2024-10-02 | 3.x | [tag v2.2.25](https://github.com/swagger-api/swagger-core/tree/v2.2.25) | Supported 2.2.24 | 2024-09-23 | 3.x | [tag v2.2.24](https://github.com/swagger-api/swagger-core/tree/v2.2.24) | Supported 2.2.23 | 2024-08-28 | 3.x | [tag v2.2.23](https://github.com/swagger-api/swagger-core/tree/v2.2.23) | Supported 2.2.22 | 2024-05-15 | 3.x | [tag v2.2.22](https://github.com/swagger-api/swagger-core/tree/v2.2.22) | Supported 2.2.21 | 2024-03-20 | 3.x | [tag v2.2.21](https://github.com/swagger-api/swagger-core/tree/v2.2.21) | Supported 2.2.20 | 2023-12-19 | 3.x | [tag v2.2.20](https://github.com/swagger-api/swagger-core/tree/v2.2.20) | Supported 2.2.19 | 2023-11-10 | 3.x | [tag v2.2.19](https://github.com/swagger-api/swagger-core/tree/v2.2.19) | Supported 2.2.18 | 2023-10-25 | 3.x | [tag v2.2.18](https://github.com/swagger-api/swagger-core/tree/v2.2.18) | Supported 2.2.17 | 2023-10-12 | 3.x | [tag v2.2.17](https://github.com/swagger-api/swagger-core/tree/v2.2.17) | Supported 2.2.16 | 2023-09-18 | 3.x | [tag v2.2.16](https://github.com/swagger-api/swagger-core/tree/v2.2.16) | Supported 2.2.15 | 2023-07-08 | 3.x | [tag v2.2.15](https://github.com/swagger-api/swagger-core/tree/v2.2.15) | Supported 2.2.14 | 2023-06-26 | 3.x | [tag v2.2.14](https://github.com/swagger-api/swagger-core/tree/v2.2.14) | Supported 2.2.13 | 2023-06-24 | 3.x | [tag v2.2.13](https://github.com/swagger-api/swagger-core/tree/v2.2.13) | Supported 2.2.12 | 2023-06-13 | 3.x | [tag v2.2.12](https://github.com/swagger-api/swagger-core/tree/v2.2.12) | Supported 2.2.11 | 2023-06-01 | 3.x | [tag v2.2.11](https://github.com/swagger-api/swagger-core/tree/v2.2.11) | Supported 2.2.10 | 2023-05-15 | 3.x | [tag v2.2.10](https://github.com/swagger-api/swagger-core/tree/v2.2.10) | Supported 2.2.9 | 2023-03-20 | 3.x | [tag v2.2.9](https://github.com/swagger-api/swagger-core/tree/v2.2.9) | Supported 2.2.8 | 2023-01-06 | 3.x | [tag v2.2.8](https://github.com/swagger-api/swagger-core/tree/v2.2.8) | Supported 2.2.7 | 2022-11-15 | 3.0 | [tag v2.2.7](https://github.com/swagger-api/swagger-core/tree/v2.2.7) | Supported 2.2.6 | 2022-11-02 | 3.0 | [tag v2.2.6](https://github.com/swagger-api/swagger-core/tree/v2.2.6) | Supported 2.2.5 | 2022-11-02 | 3.0 | [tag v2.2.5](https://github.com/swagger-api/swagger-core/tree/v2.2.5) | Supported 2.2.4 | 2022-10-16 | 3.0 | [tag v2.2.4](https://github.com/swagger-api/swagger-core/tree/v2.2.4) | Supported 2.2.3 | 2022-09-27 | 3.0 | [tag v2.2.3](https://github.com/swagger-api/swagger-core/tree/v2.2.3) | Supported 2.2.2 | 2022-07-20 | 3.0 | [tag v2.2.2](https://github.com/swagger-api/swagger-core/tree/v2.2.2) | Supported 2.2.1 | 2022-06-15 | 3.0 | [tag v2.2.1](https://github.com/swagger-api/swagger-core/tree/v2.2.1) | Supported 2.2.0 | 2022-04-04 | 3.0 | [tag v2.2.0](https://github.com/swagger-api/swagger-core/tree/v2.2.0) | Supported 2.1.13 | 2022-02-07 | 3.0 | [tag v2.1.13](https://github.com/swagger-api/swagger-core/tree/v2.1.13) | Supported 2.1.12 | 2021-12-23 | 3.0 | [tag v2.1.12](https://github.com/swagger-api/swagger-core/tree/v2.1.12) | Supported 2.1.11 | 2021-09-29 | 3.0 | [tag v2.1.11](https://github.com/swagger-api/swagger-core/tree/v2.1.11) | Supported 2.1.10 | 2021-06-28 | 3.0 | [tag v2.1.10](https://github.com/swagger-api/swagger-core/tree/v2.1.10) | Supported 2.1.9 | 2021-04-20 | 3.0 | [tag v2.1.9](https://github.com/swagger-api/swagger-core/tree/v2.1.9) | Supported 2.1.8 | 2021-04-18 | 3.0 | [tag v2.1.8](https://github.com/swagger-api/swagger-core/tree/v2.1.8) | Supported 2.1.7 | 2021-02-18 | 3.0 | [tag v2.1.7](https://github.com/swagger-api/swagger-core/tree/v2.1.7) | Supported 2.1.6 | 2020-12-04 | 3.0 | [tag v2.1.6](https://github.com/swagger-api/swagger-core/tree/v2.1.6) | Supported 2.1.5 | 2020-10-01 | 3.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-core/tree/v2.1.5) | Supported 2.1.4 | 2020-07-24 | 3.0 | [tag v2.1.4](https://github.com/swagger-api/swagger-core/tree/v2.1.4) | Supported 2.1.3 | 2020-06-27 | 3.0 | [tag v2.1.3](https://github.com/swagger-api/swagger-core/tree/v2.1.3) | Supported 2.1.2 | 2020-04-01 | 3.0 | [tag v2.1.2](https://github.com/swagger-api/swagger-core/tree/v2.1.2) | Supported 2.1.1 | 2020-01-02 | 3.0 | [tag v2.1.1](https://github.com/swagger-api/swagger-core/tree/v2.1.1) | Supported 2.1.0 | 2019-11-16 | 3.0 | [tag v2.1.0](https://github.com/swagger-api/swagger-core/tree/v2.1.0) | Supported 2.0.10 | 2019-10-11 | 3.0 | [tag v2.0.10](https://github.com/swagger-api/swagger-core/tree/v2.0.10) | Supported 2.0.9 | 2019-08-22 | 3.0 | [tag v2.0.9](https://github.com/swagger-api/swagger-core/tree/v2.0.9) | Supported 2.0.8 | 2019-04-24 | 3.0 | [tag v2.0.8](https://github.com/swagger-api/swagger-core/tree/v2.0.8) | Supported 2.0.7 | 2019-02-18 | 3.0 | [tag v2.0.7](https://github.com/swagger-api/swagger-core/tree/v2.0.7) | Supported 2.0.6 | 2018-11-27 | 3.0 | [tag v2.0.6](https://github.com/swagger-api/swagger-core/tree/v2.0.6) | Supported 2.0.5 | 2018-09-19 | 3.0 | [tag v2.0.5](https://github.com/swagger-api/swagger-core/tree/v2.0.5) | Supported 2.0.4 | 2018-09-05 | 3.0 | [tag v2.0.4](https://github.com/swagger-api/swagger-core/tree/v2.0.4) | Supported 2.0.3 | 2018-08-09 | 3.0 | [tag v2.0.3](https://github.com/swagger-api/swagger-core/tree/v2.0.3) | Supported 1.6.14 (**current stable**)| 2024-03-19 | 2.0 | [tag v1.6.14](https://github.com/swagger-api/swagger-core/tree/v1.6.14) | Supported 1.6.13 | 2024-01-26 | 2.0 | [tag v1.6.13](https://github.com/swagger-api/swagger-core/tree/v1.6.13) | Supported 1.6.12 | 2023-10-14 | 2.0 | [tag v1.6.12](https://github.com/swagger-api/swagger-core/tree/v1.6.12) | Supported 1.6.11 | 2023-05-15 | 2.0 | [tag v1.6.11](https://github.com/swagger-api/swagger-core/tree/v1.6.11) | Supported 1.6.10 | 2023-03-21 | 2.0 | [tag v1.6.10](https://github.com/swagger-api/swagger-core/tree/v1.6.10) | Supported 1.6.9 | 2022-11-15 | 2.0 | [tag v1.6.9](https://github.com/swagger-api/swagger-core/tree/v1.6.9) | Supported 1.6.8 | 2022-10-16 | 2.0 | [tag v1.6.8](https://github.com/swagger-api/swagger-core/tree/v1.6.8) | Supported 1.6.7 | 2022-09-27 | 2.0 | [tag v1.6.7](https://github.com/swagger-api/swagger-core/tree/v1.6.7) | Supported 1.6.6 | 2022-04-04 | 2.0 | [tag v1.6.6](https://github.com/swagger-api/swagger-core/tree/v1.6.6) | Supported 1.6.5 | 2022-02-07 | 2.0 | [tag v1.6.5](https://github.com/swagger-api/swagger-core/tree/v1.6.5) | Supported 1.6.4 | 2021-12-23 | 2.0 | [tag v1.6.4](https://github.com/swagger-api/swagger-core/tree/v1.6.4) | Supported 1.6.3 | 2021-09-29 | 2.0 | [tag v1.6.3](https://github.com/swagger-api/swagger-core/tree/v1.6.3) | Supported 1.6.2 | 2020-07-01 | 2.0 | [tag v1.6.2](https://github.com/swagger-api/swagger-core/tree/v1.6.2) | Supported 1.6.1 | 2020-04-01 | 2.0 | [tag v1.6.1](https://github.com/swagger-api/swagger-core/tree/v1.6.1) | Supported 1.6.0 | 2019-11-16 | 2.0 | [tag v1.6.0](https://github.com/swagger-api/swagger-core/tree/v1.6.0) | Supported 1.5.24 | 2019-10-11 | 2.0 | [tag v1.5.24](https://github.com/swagger-api/swagger-core/tree/v1.5.24) | Supported 1.5.23 | 2019-08-22 | 2.0 | [tag v1.5.23](https://github.com/swagger-api/swagger-core/tree/v1.5.23) | Supported 1.5.22 | 2019-02-18 | 2.0 | [tag v1.5.22](https://github.com/swagger-api/swagger-core/tree/v1.5.22) | Supported 1.5.21 | 2018-08-09 | 2.0 | [tag v1.5.21](https://github.com/swagger-api/swagger-core/tree/v1.5.21) | Supported 1.5.20 | 2018-05-23 | 2.0 | [tag v1.5.20](https://github.com/swagger-api/swagger-core/tree/v1.5.20) | Supported 2.0.2 | 2018-05-23 | 3.0 | [tag v2.0.2](https://github.com/swagger-api/swagger-core/tree/v2.0.2) | Supported 2.0.1 | 2018-04-16 | 3.0 | [tag v2.0.1](https://github.com/swagger-api/swagger-core/tree/v2.0.1) | Supported 1.5.19 | 2018-04-16 | 2.0 | [tag v1.5.19](https://github.com/swagger-api/swagger-core/tree/v1.5.19) | Supported 2.0.0 | 2018-03-20 | 3.0 | [tag v2.0.0](https://github.com/swagger-api/swagger-core/tree/v2.0.0) | Supported 2.0.0-rc4 | 2018-01-22 | 3.0 | [tag v2.0.0-rc4](https://github.com/swagger-api/swagger-core/tree/v2.0.0-rc4) | Supported 2.0.0-rc3 | 2017-11-21 | 3.0 | [tag v2.0.0-rc3](https://github.com/swagger-api/swagger-core/tree/v2.0.0-rc3) | Supported 2.0.0-rc2 | 2017-09-29 | 3.0 | [tag v2.0.0-rc2](https://github.com/swagger-api/swagger-core/tree/v2.0.0-rc2) | Supported 2.0.0-rc1 | 2017-08-17 | 3.0 | [tag v2.0.0-rc1](https://github.com/swagger-api/swagger-core/tree/v2.0.0-rc1) | Supported 1.5.18 | 2018-01-22 | 2.0 | [tag v1.5.18](https://github.com/swagger-api/swagger-core/tree/v1.5.18) | Supported 1.5.17 | 2017-11-21 | 2.0 | [tag v1.5.17](https://github.com/swagger-api/swagger-core/tree/v1.5.17) | Supported 1.5.16 | 2017-07-15 | 2.0 | [tag v1.5.16](https://github.com/swagger-api/swagger-core/tree/v1.5.16) | Supported 1.3.12 | 2014-12-23 | 1.2 | [tag v1.3.12](https://github.com/swagger-api/swagger-core/tree/v1.3.12) | Supported 1.2.4 | 2013-06-19 | 1.1 | [tag swagger-project_2.10.0-1.2.4](https://github.com/swagger-api/swagger-core/tree/swagger-project_2.10.0-1.2.4) | Deprecated 1.0.0 | 2011-10-16 | 1.0 | [tag v1.0](https://github.com/swagger-api/swagger-core/tree/v1.0) | Deprecated ### Change History If you're interested in the change history of swagger and the Swagger Core framework, see [here](https://github.com/swagger-api/swagger-core/releases). ### Prerequisites You need the following installed and available in your $PATH: * Java 11 * Apache maven 3.0.4 or greater * Jackson 2.4.5 or greater ### To build from source (currently 2.2.46-SNAPSHOT) ``` # first time building locally mvn -N ``` Subsequent builds: ``` mvn install ``` This will build the modules. Of course if you don't want to build locally you can grab artifacts from maven central: `https://repo1.maven.org/maven2/io/swagger/core/` ## Sample Apps The samples have moved to [a new repository](https://github.com/swagger-api/swagger-samples/tree/2.0) and contain various integrations and configurations. ## Security contact Please disclose any security-related issues or vulnerabilities by emailing [security@swagger.io](mailto:security@swagger.io), instead of using the public issue tracker. ================================================ FILE: modules/swagger-annotations/.gitignore ================================================ /bin/ ================================================ FILE: modules/swagger-annotations/pom.xml ================================================ io.swagger.core.v3 swagger-project 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-annotations swagger-annotations swagger-annotations src/main/java install biz.aQute.bnd bnd-maven-plugin org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF io.swagger.v3.oas.annotations release org.apache.maven.plugins maven-enforcer-plugin ${enforcer-plugin-version} enforce-no-snapshots enforce Publish javadocs for a SNAPSHOT is not allowed. true maven-resources-plugin 3.1.0 copy-resources deploy copy-resources ${project.build.directory}/javadocprep/swagger-core/${project.version}/apidocs ${project.build.directory}/apidocs true jakarta.ws.rs jakarta.ws.rs-api test org.testng testng test ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/ExternalDocumentation.java ================================================ package io.swagger.v3.oas.annotations; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.METHOD; /** * The annotation may be used at method level or as field of {@link Operation} to add a reference to an external * resource for extended documentation of an Operation (OpenAPI specification). *

It may also be used to add external documentation to {@link io.swagger.v3.oas.annotations.tags.Tag}, * {@link io.swagger.v3.oas.annotations.headers.Header} or {@link io.swagger.v3.oas.annotations.media.Schema}, * or as field of {@link OpenAPIDefinition}.

* * @see External Documentation (OpenAPI specification) * @see OpenAPIDefinition **/ @Target({METHOD, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface ExternalDocumentation { /** * A short description of the target documentation. * * @return the documentation description **/ String description() default ""; /** * The URL for the target documentation. Value must be in the format of a URL. * * @return the documentation URL **/ String url() default ""; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/Hidden.java ================================================ package io.swagger.v3.oas.annotations; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; /** * Marks a given resource, class or bean type as hidden, skipping while reading / resolving **/ @Target({METHOD, TYPE, FIELD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Hidden { } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/OpenAPI31.java ================================================ package io.swagger.v3.oas.annotations; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; @Target({METHOD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface OpenAPI31 {} ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/OpenAPIDefinition.java ================================================ package io.swagger.v3.oas.annotations; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.tags.Tag; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.PACKAGE; import static java.lang.annotation.ElementType.TYPE; /** * The annotation that may be used to populate OpenAPI Object fields info, tags, servers, security and externalDocs * If more than one class is annotated with {@link OpenAPIDefinition}, with the same fields defined, behaviour is inconsistent. * * @see OpenAPI (OpenAPI specification) */ @Target({TYPE, PACKAGE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface OpenAPIDefinition { /** * Provides metadata about the API. The metadata MAY be used by tooling as required. * * @return the metadata about this API */ Info info() default @Info; /** * A list of tags used by the specification with additional metadata. * The order of the tags can be used to reflect on their order by the parsing tools. * * @return the tags used by the specification with any additional metadata */ Tag[] tags() default {}; /** * An array of Server Objects, which provide connectivity information to a target server. * If the servers property is not provided, or is an empty array, the default value would be a Server Object with a url value of /. * * @return the servers of this API */ Server[] servers() default {}; /** * A declaration of which security mechanisms can be used across the API. * * @return the array of servers used for this API */ SecurityRequirement[] security() default {}; /** * Any additional external documentation for the API * * @return the external documentation for this API. */ ExternalDocumentation externalDocs() default @ExternalDocumentation; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/Operation.java ================================================ package io.swagger.v3.oas.annotations; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.servers.Server; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; /** * The annotation may be used to define a resource method as an OpenAPI Operation, and/or to define additional * properties for the Operation. * *

Note: swagger-jaxrs2 reader engine includes by default also methods of scanned resources which are not annotated * with @Operation, as long as a jax-rs @Path is defined at class and/or method level, together with the http method * annotation (@GET, @POST, etc).

*

This behaviour is controlled by configuration property `scanAllResources` which defaults to true. By setting this * flag to false only @{@link Operation} annotated methods are considered.

* *

The following fields can also alternatively be defined at method level (as repeatable annotations in case of arrays), * in this case method level annotations take precedence over @{@link Operation} annotation fields:

* *
    *
  • tags: @{@link io.swagger.v3.oas.annotations.tags.Tag}
  • *
  • externalDocs: @{@link ExternalDocumentation}
  • *
  • parameters: @{@link Parameter}
  • *
  • responses: @{@link ApiResponse}
  • *
  • security: @{@link SecurityRequirement}
  • *
  • servers: @{@link Server}
  • *
  • extensions: @{@link Extension}
  • *
  • hidden: @{@link Hidden}
  • *
* * @see Operation (OpenAPI specification) **/ @Target({METHOD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Operation { /** * The HTTP method for this operation. * * @return the HTTP method of this operation **/ String method() default ""; /** * Tags can be used for logical grouping of operations by resources or any other qualifier. * * @return the list of tags associated with this operation **/ String[] tags() default {}; /** * Provides a brief description of this operation. Should be 120 characters or less for proper visibility in Swagger-UI. * * @return a summary of this operation **/ String summary() default ""; /** * A verbose description of the operation. * * @return a description of this operation **/ String description() default ""; /** * Request body associated to the operation. * * @return a request body. */ RequestBody requestBody() default @RequestBody(); /** * Additional external documentation for this operation. * * @return additional documentation about this operation **/ ExternalDocumentation externalDocs() default @ExternalDocumentation(); /** * The operationId is used by third-party tools to uniquely identify this operation. * * @return the ID of this operation **/ String operationId() default ""; /** * An optional array of parameters which will be added to any automatically detected parameters in the method itself. * * @return the list of parameters for this operation **/ Parameter[] parameters() default {}; /** * The list of possible responses as they are returned from executing this operation. * * @return the list of responses for this operation **/ ApiResponse[] responses() default {}; /** * Allows an operation to be marked as deprecated. Alternatively use the @Deprecated annotation * * @return whether or not this operation is deprecated **/ boolean deprecated() default false; /** * A declaration of which security mechanisms can be used for this operation. * * @return the array of security requirements for this Operation */ SecurityRequirement[] security() default {}; /** * An alternative server array to service this operation. * * @return the list of servers hosting this operation **/ Server[] servers() default {}; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * Allows this operation to be marked as hidden * * @return whether or not this operation is hidden */ boolean hidden() default false; /** * Ignores JsonView annotations while resolving operations and types. * * @return whether or not to ignore JsonView annotations */ boolean ignoreJsonView() default false; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/Parameter.java ================================================ package io.swagger.v3.oas.annotations; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; /** * The annotation may be used on a method parameter to define it as a parameter for the operation, and/or to define * additional properties for the Parameter. It can also be used independently in {@link Operation#parameters()} or at * method level to add a parameter to the operation, even if not bound to any method parameter. * *

swagger-jaxrs2 reader engine considers this annotation along with JAX-RS annotations, parameter type and context * as input to resolve a method parameter into an OpenAPI Operation parameter.

* *

For method parameters bound to the request body, see {@link io.swagger.v3.oas.annotations.parameters.RequestBody}

* * @see Parameter (OpenAPI specification) * @see io.swagger.v3.oas.annotations.parameters.RequestBody * @see Operation * @see Schema **/ @Target({PARAMETER, METHOD, FIELD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Repeatable(Parameters.class) @Inherited public @interface Parameter { /** * The name of the parameter. * * @return the parameter's name **/ String name() default ""; /** * The location of the parameter. Possible values are "query", "header", "path" or "cookie". Ignored when empty string. * * @return the parameter's location **/ ParameterIn in() default ParameterIn.DEFAULT; /** * Additional description data to provide on the purpose of the parameter * * @return the parameter's description **/ String description() default ""; /** * Determines whether this parameter is mandatory. If the parameter location is "path", this property is required and its value must be true. Otherwise, the property may be included and its default value is false. * * @return whether or not the parameter is required **/ boolean required() default false; /** * Specifies that a parameter is deprecated and should be transitioned out of usage. * * @return whether or not the parameter is deprecated **/ boolean deprecated() default false; /** * When true, allows sending an empty value. If false, the parameter will be considered \"null\" if no value is present. This may create validation errors when the parameter is required. * * @return whether or not the parameter allows empty values **/ boolean allowEmptyValue() default false; /** * Describes how the parameter value will be serialized depending on the type of the parameter value. Default values (based on value of in): for query - form; for path - simple; for header - simple; for cookie - form. Ignored if the properties content or array are specified. * * @return the style of the parameter **/ ParameterStyle style() default ParameterStyle.DEFAULT; /** * When this is true, parameter values of type array or object generate separate parameters for each value of the array or key-value pair of the map. For other types of parameters this property has no effect. When style is form, the default value is true. For all other styles, the default value is false. Ignored if the properties content or array are specified. * * @return whether or not to expand individual array members **/ Explode explode() default Explode.DEFAULT; /** * Determines whether the parameter value should allow reserved characters, as defined by RFC3986. This property only applies to parameters with an in value of query. The default value is false. Ignored if the properties content or array are specified. * * @return whether or not the parameter allows reserved characters **/ boolean allowReserved() default false; /** * The schema defining the type used for the parameter. Ignored if the properties content or array are specified. * * @return the schema of the parameter **/ Schema schema() default @Schema(); /** * The schema of the array that defines this parameter. Ignored if the property content is specified. * * @return the schema of the array */ ArraySchema array() default @ArraySchema(); /** * The representation of this parameter, for different media types. * * @return the content of the parameter **/ Content[] content() default {}; /** * Allows this parameter to be marked as hidden * * @return whether or not this parameter is hidden */ boolean hidden() default false; /** * An array of examples of the schema used to show the use of the associated schema. * * @return array of examples of the parameter **/ ExampleObject[] examples() default {}; /** * Provides an example of the schema. When associated with a specific media type, the example string shall be parsed by the consumer to be treated as an object or an array. Ignored if the properties examples, content or array are specified. * * @return an example of the parameter **/ String example() default ""; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * A reference to a parameter defined in components parameter. * * @since 2.0.3 * @return the reference **/ String ref() default ""; Class[] validationGroups() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/Parameters.java ================================================ package io.swagger.v3.oas.annotations; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; /** * Container for repeatable {@link Parameter} annotation * * @see Parameter */ @Target({METHOD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Parameters { /** * An array of Parameters Objects for the operation * * @return the parameters */ Parameter[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/StringToClassMapItem.java ================================================ package io.swagger.v3.oas.annotations; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; @Target({METHOD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface StringToClassMapItem { String key(); Class value(); } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/Webhook.java ================================================ package io.swagger.v3.oas.annotations; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; /** * The annotation may be used to define a method as an OpenAPI Webhook. * * @see Webhook (OpenAPI specification) * @see io.swagger.v3.oas.annotations.OpenAPIDefinition **/ @Target({METHOD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @OpenAPI31 public @interface Webhook { /** * Provides the name related to this webhook. * @return webhook name */ String name(); /** * Provides the operation related to this webhook. * @return webhook operation */ Operation operation(); } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/Webhooks.java ================================================ package io.swagger.v3.oas.annotations; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; /** * Container for repeatable {@link Webhook} annotation * * @see Webhook */ @Target({TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @OpenAPI31 public @interface Webhooks { /** * An array of Webhook annotations * * @return the array of the Webhook **/ Webhook[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/callbacks/Callback.java ================================================ package io.swagger.v3.oas.annotations.callbacks; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; /** * The annotation may be used at method level to add one ore more callbacks to the operation definition. * * @see Callback (OpenAPI specification) **/ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Repeatable(Callbacks.class) @Inherited public @interface Callback { /** * The friendly name used to refer to this callback * * @return the name of the callback **/ String name() default ""; /** * An absolute URL which defines the destination which will be called with the supplied operation definition. * * @return the callback URL */ String callbackUrlExpression() default ""; /** * The array of operations that will be called out-of band * * @return the callback operations **/ Operation[] operation() default {}; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * A reference to a Callback defined in components Callbacks. * * @since 2.0.3 * @return the reference **/ String ref() default ""; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/callbacks/Callbacks.java ================================================ package io.swagger.v3.oas.annotations.callbacks; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; /** * Container for repeatable {@link Callback} annotation * * @see Callback */ @Target({METHOD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Callbacks { /** * An array of Callback annotations which are a map of possible out-of band callbacks related to the parent operation * * @return the array of the callbacks **/ Callback[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/enums/Explode.java ================================================ package io.swagger.v3.oas.annotations.enums; public enum Explode { DEFAULT, FALSE, TRUE; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/enums/ParameterIn.java ================================================ package io.swagger.v3.oas.annotations.enums; public enum ParameterIn { DEFAULT(""), HEADER("header"), QUERY("query"), PATH("path"), COOKIE("cookie"); private String value; ParameterIn(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/enums/ParameterStyle.java ================================================ package io.swagger.v3.oas.annotations.enums; public enum ParameterStyle { DEFAULT(""), MATRIX("matrix"), LABEL("label"), FORM("form"), SPACEDELIMITED("spaceDelimited"), PIPEDELIMITED("pipeDelimited"), DEEPOBJECT("deepObject"), SIMPLE("simple"); private String value; ParameterStyle(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/enums/SecuritySchemeIn.java ================================================ package io.swagger.v3.oas.annotations.enums; public enum SecuritySchemeIn { DEFAULT(""), HEADER("header"), QUERY("query"), COOKIE("cookie"); private String value; SecuritySchemeIn(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/enums/SecuritySchemeType.java ================================================ package io.swagger.v3.oas.annotations.enums; public enum SecuritySchemeType { DEFAULT(""), APIKEY("apiKey"), HTTP("http"), OPENIDCONNECT("openIdConnect"), MUTUALTLS("mutualTLS"), OAUTH2("oauth2"); private String value; SecuritySchemeType(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/extensions/Extension.java ================================================ package io.swagger.v3.oas.annotations.extensions; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; /** * An optionally named list of extension properties. * * @see Specification extensions (OpenAPI specification) */ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Repeatable(Extensions.class) public @interface Extension { /** * An option name for these extensions. * * @return an option name for these extensions - will be prefixed with "x-" */ String name() default ""; /** * The extension properties. * * @return the actual extension properties * @see ExtensionProperty */ ExtensionProperty[] properties(); } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/extensions/ExtensionProperty.java ================================================ package io.swagger.v3.oas.annotations.extensions; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * A name/value property within a OpenApi extension * * @see Extension */ @Target(ElementType.ANNOTATION_TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ExtensionProperty { /** * The name of the property. * * @return the name of the property */ String name(); /** * The value of the property. * * @return the value of the property */ String value(); /** * If set to true, field `value` will be parsed and serialized as JSON/YAML * * @return the value of `parseValue` annotation field */ boolean parseValue() default false; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/extensions/Extensions.java ================================================ package io.swagger.v3.oas.annotations.extensions; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; /** * Container for repeatable {@link Extension} annotation * * @see Extension */ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Extensions { /** * An array of Extension annotations * * @return the array of the extensions **/ Extension[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/headers/Header.java ================================================ package io.swagger.v3.oas.annotations.headers; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be used to add one or more headers to the definition of a response or as attribute of content * encoding by defining it as field {@link io.swagger.v3.oas.annotations.responses.ApiResponse#headers()} or {@link io.swagger.v3.oas.annotations.media.Content#encoding()}. *

Please note that request headers are defined as Header {@link io.swagger.v3.oas.annotations.Parameter}.

* * @see Header (OpenAPI specification) * @see io.swagger.v3.oas.annotations.responses.ApiResponse * @see io.swagger.v3.oas.annotations.Parameter * @see io.swagger.v3.oas.annotations.media.Encoding **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Header { /** * Required: The name of the header. The name is only used as the key to store this header in a map. * * @return the header's name **/ String name(); /** * Additional description data to provide on the purpose of the header * * @return the header's description **/ String description() default ""; /** * The schema defining the type used for the header. Ignored if the properties content or array are specified. * * @return the schema of the header **/ Schema schema() default @Schema(); /** * Determines whether this header is mandatory. The property may be included and its default value is false. * * @return whether or not the header is required **/ boolean required() default false; /** * Specifies that a header is deprecated and should be transitioned out of usage. * * @return whether or not the header is deprecated **/ boolean deprecated() default false; /** * A reference to a header defined in components headers. * * @since 2.0.3 * @return the reference **/ String ref() default ""; /** * When this is true, parameter values of type array or object generate separate parameters for each value of the array or key-value pair of the map. For other types of parameters this property has no effect. When style is form, the default value is true. For all other styles, the default value is false. Ignored if the properties content or array are specified. * * @return whether or not to expand individual array members **/ Explode explode() default Explode.DEFAULT; /** * Allows this header to be marked as hidden * * @return whether or not this header is hidden */ boolean hidden() default false; /** * Provides an example of the schema. When associated with a specific media type, the example string shall be parsed by the consumer to be treated as an object or an array. Ignored if the properties examples, content or array are specified. * * @return an example of the header **/ String example() default ""; /** * An array of examples of the schema used to show the use of the associated schema. * * @return array of examples of the header **/ ExampleObject[] examples() default {}; /** * The schema of the array that defines this header. Ignored if the property content is specified. * * @return the schema of the array */ ArraySchema array() default @ArraySchema(); } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/info/Contact.java ================================================ package io.swagger.v3.oas.annotations.info; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be used in {@link Info#contact()} to define a contact for the OpenAPI spec. * * @see Contact (OpenAPI specification) * @see io.swagger.v3.oas.annotations.OpenAPIDefinition * @see Info **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) public @interface Contact { /** * The identifying name of the contact person/organization. * * @return the name of the contact **/ String name() default ""; /** * The URL pointing to the contact information. Must be in the format of a URL. * * @return the URL of the contact **/ String url() default ""; /** * The email address of the contact person/organization. Must be in the format of an email address. * * @return the email address of the contact **/ String email() default ""; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/info/Info.java ================================================ package io.swagger.v3.oas.annotations.info; import io.swagger.v3.oas.annotations.OpenAPI31; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be used in {@link io.swagger.v3.oas.annotations.OpenAPIDefinition#info()} to populate the Info section of the OpenAPI document. * * @see Info (OpenAPI specification) * @see Info (OpenAPI specification) * @see io.swagger.v3.oas.annotations.OpenAPIDefinition **/ @Target({ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Info { /** * The title of the application. * * @return the application's title **/ String title() default ""; /** * A short description of the application. CommonMark syntax can be used for rich text representation. * * @return the application's description **/ String description() default ""; /** * A URL to the Terms of Service for the API. Must be in the format of a URL. * * @return the application's terms of service **/ String termsOfService() default ""; /** * The contact information for the exposed API. * * @return a contact for the application **/ Contact contact() default @Contact(); /** * The license information for the exposed API. * * @return the license of the application **/ License license() default @License(); /** * The version of the API definition. * * @return the application's version **/ String version() default ""; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * A short API summary. * * @since 2.2.12 / OpenAPI 3.1 * @return API summary **/ @OpenAPI31 String summary() default ""; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/info/License.java ================================================ package io.swagger.v3.oas.annotations.info; import io.swagger.v3.oas.annotations.OpenAPI31; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be used in {@link Info#license()} to define a license for the OpenAPI spec. * * @see License (OpenAPI 3.0 pecification) * @see License (OpenAPI 3.1 specification) * @see io.swagger.v3.oas.annotations.OpenAPIDefinition * @see Info **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) public @interface License { /** * The license name used for the API. * * @return the name of the license **/ String name() default ""; /** * A URL to the license used for the API. MUST be in the format of a URL. * * @return URL to the license **/ String url() default ""; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * An identifier for a License instance. * * @since 2.2.12 / OpenAPI 3.1 * @return the identifier of the license **/ @OpenAPI31 String identifier() default ""; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/links/Link.java ================================================ package io.swagger.v3.oas.annotations.links; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.servers.Server; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be applied in {@link io.swagger.v3.oas.annotations.responses.ApiResponse#links()} to add OpenAPI links to a response. * * @see Link (OpenAPI specification) * @see io.swagger.v3.oas.annotations.responses.ApiResponse **/ @Target({ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Link { /** * The name of this link. * * @return the link's name **/ String name() default ""; /** * A relative or absolute reference to an OAS operation. This field is mutually exclusive of the operationId field, and must point to an Operation Object. Relative operationRef values may be used to locate an existing Operation Object in the OpenAPI definition. Ignored if the operationId property is specified. * * @return an operation reference **/ String operationRef() default ""; /** * The name of an existing, resolvable OAS operation, as defined with a unique operationId. This field is mutually exclusive of the operationRef field. * * @return an operation ID **/ String operationId() default ""; /** * Array of parameters to pass to an operation as specified with operationId or identified via operationRef. * * @return the list of parameters for this link **/ LinkParameter[] parameters() default {}; /** * A description of the link. CommonMark syntax may be used for rich text representation. * * @return the link's description **/ String description() default ""; /** * A literal value or {expression} to use as a request body when calling the target operation. * * @return the request body of this link **/ String requestBody() default ""; /** * An alternative server to service this operation. * * @return the server associated to this link **/ Server server() default @Server; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * A reference to a link defined in components links. * * @since 2.0.3 * @return the reference **/ String ref() default ""; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/links/LinkParameter.java ================================================ package io.swagger.v3.oas.annotations.links; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Represents a parameter to pass to an operation as specified with operationId or identified via operationRef. **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface LinkParameter { /** * The name of this link parameter. * * @return the parameter's name **/ String name() default ""; /** * A constant or an expression to be evaluated and passed to the linked operation. * * @return the parameter's value **/ String expression() default ""; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/ArraySchema.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.OpenAPI31; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; /** * The annotation may be used to define a schema of type "array" for a set of elements of the OpenAPI spec, and/or to define additional * properties for the schema. It is applicable e.g. to parameters, schema classes (aka "models"), properties of such * models, request and response content, header. * *

swagger-core resolver and swagger-jaxrs2 reader engine consider this annotation along with JAX-RS annotations, * element type and context as input to resolve the annotated element into an OpenAPI schema definition for such element.

* *

The annotation {@link Schema} shall be used for non array elements; {@link ArraySchema} and {@link Schema} cannot * coexist

* * @see Schema (OpenAPI specification) * @see Schema (OpenAPI specification) * @see Schema **/ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface ArraySchema { /** * The schemas of the items in the array * * @since 2.2.12 * * @deprecated since 2.2.21, use {@link #schema()} instead. Marked for removal in future versions. * @return items */ @Deprecated Schema items() default @Schema; /** * The schema of the items in the array * * @return schema */ Schema schema() default @Schema; /** * Allows to define the properties to be resolved into properties of the schema of type `array` (not the ones of the * `items` of such schema which are defined in {@link #schema() schema}. * * @return arraySchema * * @since 2.0.2 */ Schema arraySchema() default @Schema; /** * sets the maximum number of items in an array. Ignored if value is Integer.MIN_VALUE. * * @return integer representing maximum number of items in array **/ int maxItems() default Integer.MIN_VALUE; /** * sets the minimum number of items in an array. Ignored if value is Integer.MAX_VALUE. * * @return integer representing minimum number of items in array **/ int minItems() default Integer.MAX_VALUE; /** * determines whether an array of items will be unique * * @return boolean - whether items in an array are unique or repeating **/ boolean uniqueItems() default false; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * Specifies contains constrictions expressions. * * @since 2.2.12 / OpenAPI 3.1 * @return contains expression. */ @OpenAPI31 Schema contains() default @Schema; /** * Provides max contains related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return max contains */ @OpenAPI31 int maxContains() default 0; /** * Provides min contains related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return min contains */ @OpenAPI31 int minContains() default 0; /** * Provides unevaluted items to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return unevaluated items */ @OpenAPI31 Schema unevaluatedItems() default @Schema; /** * Provides prefix items to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return prefixItems */ @OpenAPI31 Schema[] prefixItems() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Content.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.OpenAPI31; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be used to define the content/media type of a parameter, request or response, by defining it as * field {@link io.swagger.v3.oas.annotations.Parameter#content()}, {@link io.swagger.v3.oas.annotations.parameters.RequestBody#content()} or {@link io.swagger.v3.oas.annotations.responses.ApiResponse#content()}. *

If {@link Content#schema()} is defined, swagger-jaxrs2 reader engine will consider it along with * JAX-RS annotations, element type and context as input to resolve the annotated element into an OpenAPI schema * definition for such element.

* * @see Example (OpenAPI specification) * @see Schema * @see io.swagger.v3.oas.annotations.Parameter * @see io.swagger.v3.oas.annotations.responses.ApiResponse * @see io.swagger.v3.oas.annotations.parameters.RequestBody **/ @Target({ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Content { /** * The media type that this object applies to. * * @return the media type value **/ String mediaType() default ""; /** * An array of examples used to show the use of the associated schema. * * @return the list of examples **/ ExampleObject[] examples() default {}; /** * The schema defining the type used for the content. * * @return the schema of this media type **/ Schema schema() default @Schema(); /** * The schema properties defined for schema provided in @Schema * * @since 2.2.0 * @return the schema properties */ SchemaProperty[] schemaProperties() default {}; /** * The additionalProperties schema defined for schema provided in @Schema * If the additionalProperties schema is an array, use additionalPropertiesArraySchema * * @since 2.2.0 * @return the additionalProperties schema */ Schema additionalPropertiesSchema() default @Schema(); /** * The additionalProperties array schema defined for schema provided in @Schema * If the additionalProperties schema is not an array, use additionalPropertiesSchema * * @since 2.2.16 * @return the additionalProperties array schema */ ArraySchema additionalPropertiesArraySchema() default @ArraySchema(); /** * The schema of the array that defines the type used for the content. * * @return the schema of the array */ ArraySchema array() default @ArraySchema(); /** * An array of encodings * The key, being the property name, MUST exist in the schema as a property. * * @return the array of encodings */ Encoding[] encoding() default {}; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * Subschemas to be applied for a given condition. * * @since 2.2.12 / OpenAPI 3.1 * @return list of dependent schemas. */ @OpenAPI31 DependentSchema[] dependentSchemas() default {}; /** * Provides the content schema related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return content schema */ @OpenAPI31 Schema contentSchema() default @Schema(); /** * Provides property names related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return proeprty names */ @OpenAPI31 Schema propertyNames() default @Schema(); /** * Provides the if sub schema related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return if schema */ @OpenAPI31 Schema _if() default @Schema(); /** * Provides the then sub schema related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return then schema */ @OpenAPI31 Schema _then() default @Schema(); /** * Provides the else sub schema related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return else schema */ @OpenAPI31 Schema _else() default @Schema(); /** * Set schemas to validate according a given condition. * * @since 2.2.12 / OpenAPI 3.1 * @return not schema to be validated **/ Schema not() default @Schema(); /** * Provides the oneOf sub schemas related to this schema. * * @since 2.2.12 / OpenAPI 3.1 * @return oneOf sub schemas **/ Schema[] oneOf() default {}; /** * Provides the anyOf sub schemas related to this schema. * * @since 2.2.12 / OpenAPI 3.1 * @return anyOf sub schemas **/ Schema[] anyOf() default {}; /** * Provides the allOf sub schemas related to this schema.. * * @since 2.2.12 / OpenAPI 3.1 * @return allOf sub schemas **/ Schema[] allOf() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/DependentRequired.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.OpenAPI31; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; /** * The annotation may be used to define dependent schemas for an Object Schema * * @see Schema * * @since 2.2.12 / OpenAPI 3.1 **/ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Repeatable(DependentRequiredMap.class) @OpenAPI31 public @interface DependentRequired { /** * The name. * * @return the name **/ String name() default ""; /** * The values of the dependent schema. * * @return the schema **/ String[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/DependentRequiredMap.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.OpenAPI31; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; /** * Container for repeatable {@link DependentRequired} annotation * * @since 2.2.12 / OpenAPI 3.1 * @see DependentRequired */ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @OpenAPI31 public @interface DependentRequiredMap { /** * An array of DependentRequired annotations * * @return the array of the DependentRequired **/ DependentRequired[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/DependentSchema.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.OpenAPI31; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; /** * The annotation may be used to define dependent schemas for an Object Schema * * @see Schema * * @since 2.2.12 / OpenAPI 3.1 **/ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Repeatable(DependentSchemas.class) @OpenAPI31 public @interface DependentSchema { /** * The name. * * @return the key of the dependent schema map item **/ String name() default ""; /** * The value (Schema) of the dependent schema map item. * Alternative to `array()`. Applied when the schema is not of type "array". * Use `array()` when schema is of type "array" * * @return the schema **/ Schema schema() default @Schema(); /** * The value (ArraySchema) of the dependent schema map item. * Alternative to `schema()`. Applied when the schema is of type "array". * Use `schema()` when schema is not of type "array" * * @return the value of the array schema */ ArraySchema array() default @ArraySchema(); } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/DependentSchemas.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.OpenAPI31; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; /** * Container for repeatable {@link DependentSchema} annotation * * @see DependentSchema */ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @OpenAPI31 public @interface DependentSchemas { /** * An array of DependentSchema annotations * * @return the array of the DependentSchema **/ DependentSchema[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/DiscriminatorMapping.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.OpenAPI31; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be used in {@link Schema#discriminatorMapping()} to define an optional mapping definition * in scenarios involving composition / inheritance where the value of the discriminator field does not match the schema * name or implicit mapping is not possible. * *

Use {@link Schema#discriminatorProperty()} to define a discriminator property.

* * @see Discriminator (OpenAPI specification) * @see Discriminator (OpenAPI specification) * @see Schema **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface DiscriminatorMapping { /** * The property value that will be mapped to a Schema * * @return the property value **/ String value() default ""; /** * The schema that is being mapped to a property value * * @return the Schema reference **/ Class schema() default Void.class; /** * The list of optional extensions * * @since 2.2.12 / OpenAPI 3.1 * @return an optional array of extensions */ @OpenAPI31 Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Encoding.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.headers.Header; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be used to add encoding details to the definition of a parameter, request or response content, * by defining it as field {@link Content#encoding()} * * @see Encoding (OpenAPI specification) * @see Content **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Encoding { /** * The name of this encoding object instance. * This property is a key in encoding map of MediaType object and * MUST exist in a schema as a property. * * @return name of the encoding **/ String name() default ""; /** * The Content-Type for encoding a specific property. * * @return content type of the encoding **/ String contentType() default ""; /** * Describes how a specific property value will be serialized depending on its type * * @return style of the encoding **/ String style() default ""; /** * When this is true, property values of type array or object generate separate parameters for each value of the array, * or key-value-pair of the map. * * @return boolean **/ boolean explode() default false; /** * Determines whether the parameter value SHOULD allow reserved characters, * as defined by RFC3986 to be included without percent-encoding. * * @return boolean **/ boolean allowReserved() default false; /** * An array of header objects * * @return array of headers */ Header[] headers() default {}; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/ExampleObject.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be used to add one or more examples to the definition of a parameter, request or response content, * by defining it as field {@link io.swagger.v3.oas.annotations.Parameter#examples()} or {@link Content#examples()} * * @see Example (OpenAPI specification) **/ @Target({ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface ExampleObject { /** * A unique name to identify this particular example * * @return the name of the example **/ String name() default ""; /** * A brief summary of the purpose or context of the example * * @return a summary of the example **/ String summary() default ""; /** * A string representation of the example. This is mutually exclusive with the externalValue property, and ignored if the externalValue property is specified. If the media type associated with the example allows parsing into an object, it may be converted from a string * * @return the value of the example **/ String value() default ""; /** * A URL to point to an external document to be used as an example. This is mutually exclusive with the value property. * * @return an external URL of the example **/ String externalValue() default ""; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * A reference to a example defined in components examples. * * @since 2.0.3 * @return the reference **/ String ref() default ""; /** * A description of the purpose or context of the example * * @since 2.1.0 * @return a description of the example **/ String description() default ""; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/PatternProperties.java ================================================ package io.swagger.v3.oas.annotations.media; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; /** * Container for repeatable {@link PatternProperty} annotation * * @see PatternProperty */ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface PatternProperties { /** * An array of PatternProperty annotations * * @return the array of the PatternProperty **/ PatternProperty[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/PatternProperty.java ================================================ package io.swagger.v3.oas.annotations.media; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; /** * The annotation may be used in OpenAPI 3.1 schemas / JSON Schema. * * @see JSON Schema section 10.3.2.2 * @see Schema * * @since 2.1.8 **/ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Repeatable(PatternProperties.class) public @interface PatternProperty { /** * The regex. * * @return the regex **/ String regex() default ""; /** * The schema to validate against for properties matching the regex. * * @return the schema **/ Schema schema() default @Schema(); /** * The schema of the array to validate against for properties matching the regex. * * @return the schema of the array */ ArraySchema array() default @ArraySchema(); } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java ================================================ package io.swagger.v3.oas.annotations.media; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPI31; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; /** * The annotation may be used to define a Schema for a set of elements of the OpenAPI spec, and/or to define additional * properties for the schema. It is applicable e.g. to parameters, schema classes (aka "models"), properties of such * models, request and response content, header. * *

swagger-core resolver and swagger-jaxrs2 reader engine consider this annotation along with JAX-RS annotations, * element type and context as input to resolve the annotated element into an OpenAPI schema definition for such element.

*

The annotation may be used also to override partly (e.g. the name) or fully (e.g providing a completely different * representation) the schema of an element; for example if a specific class is provided as value of {@link Schema#implementation()}, * it will override the element type

* *

The annotation {@link ArraySchema} shall be used for array elements; {@link ArraySchema} and {@link Schema} cannot * coexist

* * @see Schema (OpenAPI specification) * @see Schema (OpenAPI specification) * @see ArraySchema **/ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Schema { String DEFAULT_SENTINEL = "##default"; /** * Provides a java class as implementation for this schema. When provided, additional information in the Schema annotation (except for type information) will augment the java class after introspection. * * @return a class that implements this schema **/ Class implementation() default Void.class; /** * Provides a java class to be used to disallow matching properties. * * @return a class with disallowed properties **/ Class not() default Void.class; /** * Provides an array of java class implementations which can be used to describe multiple acceptable schemas. If more than one match the derived schemas, a validation error will occur. * * @return the list of possible classes for a single match **/ Class[] oneOf() default {}; /** * Provides an array of java class implementations which can be used to describe multiple acceptable schemas. If any match, the schema will be considered valid. * * @return the list of possible class matches **/ Class[] anyOf() default {}; /** * Provides an array of java class implementations which can be used to describe multiple acceptable schemas. If all match, the schema will be considered valid * * @return the list of classes to match **/ Class[] allOf() default {}; /** * The name of the schema or property. * * @return the name of the schema **/ String name() default ""; /** * A title to explain the purpose of the schema. * * @return the title of the schema **/ String title() default ""; /** * Constrains a value such that when divided by the multipleOf, the remainder must be an integer. Ignored if the value is 0. * * @return the multiplier constraint of the schema **/ double multipleOf() default 0; /** * Sets the maximum numeric value for a property. Ignored if the value is an empty string. * * @return the maximum value for this schema **/ String maximum() default ""; /** * if true, makes the maximum value exclusive, or a less-than criteria. * * @return the exclusive maximum value for this schema **/ boolean exclusiveMaximum() default false; /** * Sets the minimum numeric value for a property. Ignored if the value is an empty string or not a number. * * @return the minimum value for this schema **/ String minimum() default ""; /** * If true, makes the minimum value exclusive, or a greater-than criteria. * * @return the exclusive minimum value for this schema **/ boolean exclusiveMinimum() default false; /** * Sets the maximum length of a string value. Ignored if the value is negative. * * @return the maximum length of this schema **/ int maxLength() default Integer.MAX_VALUE; /** * Sets the minimum length of a string value. Ignored if the value is negative. * * @return the minimum length of this schema **/ int minLength() default 0; /** * A pattern that the value must satisfy. Ignored if the value is an empty string. * * @return the pattern of this schema **/ String pattern() default ""; /** * Constrains the number of arbitrary properties when additionalProperties is defined. Ignored if value is 0. * * @return the maximum number of properties for this schema **/ int maxProperties() default 0; /** * Constrains the number of arbitrary properties when additionalProperties is defined. Ignored if value is 0. * * @return the minimum number of properties for this schema **/ int minProperties() default 0; /** * Allows multiple properties in an object to be marked as required. * * @return the list of required schema properties **/ String[] requiredProperties() default {}; /** * Mandates that the annotated item is required or not. * * @deprecated since 2.2.5, replaced by {@link #requiredMode()} * * @return whether this schema is required **/ @Deprecated boolean required() default false; /** * Allows to specify the required mode (RequiredMode.AUTO, REQUIRED, NOT_REQUIRED) * RequiredMode.AUTO: the library decides using heuristics: * - Bean Validation / nullability annotations (@NotNull, @NonNull, @NotBlank, @NotEmpty) - required * - Optional - not required * - Primitive types (int, boolean, etc.) - not required unless annotated * - Other object fields without any constraints - not required * RequiredMode.REQUIRED: will force the item to be considered as required regardless of heuristics. * RequiredMode.NOT_REQUIRED: will force the item to be considered as not required regardless of heuristics. * * @since 2.2.5 * @return the requiredMode for this schema (property) * */ RequiredMode requiredMode() default RequiredMode.AUTO; /** * A description of the schema. * * @return the schema's description **/ String description() default ""; /** * Provides an optional override for the format. If a consumer is unaware of the meaning of the format, they shall fall back to using the basic type without format. For example, if \"type: integer, format: int128\" were used to designate a very large integer, most consumers will not understand how to handle it, and fall back to simply \"type: integer\" * * @return the schema's format **/ String format() default ""; /** * References a schema definition in an external OpenAPI document. * * @return a reference to this schema **/ String ref() default ""; /** * If true, designates a value as possibly null. * * @return whether or not this schema is nullable **/ boolean nullable() default false; /** * Sets whether the value should only be read during a response but not read to during a request. * * @deprecated As of 2.0.0, replaced by {@link #accessMode()} * * @return whether or not this schema is read only * **/ @Deprecated boolean readOnly() default false; /** * Sets whether a value should only be written to during a request but not returned during a response. * * @deprecated As of 2.0.0, replaced by {@link #accessMode()} * * @return whether or not this schema is write only **/ @Deprecated boolean writeOnly() default false; /** * Allows to specify the access mode (AccessMode.READ_ONLY, WRITE_ONLY, READ_WRITE) * * AccessMode.READ_ONLY: value will not be written to during a request but may be returned during a response. * AccessMode.WRITE_ONLY: value will only be written to during a request but not returned during a response. * AccessMode.READ_WRITE: value will be written to during a request and returned during a response. * * @return the accessMode for this schema (property) * */ AccessMode accessMode() default AccessMode.AUTO; /** * Provides an example of the schema. When associated with a specific media type, the example string shall be parsed by the consumer to be treated as an object or an array. * * @return an example of this schema **/ String example() default ""; /** * Additional external documentation for this schema. * * @return additional schema documentation **/ ExternalDocumentation externalDocs() default @ExternalDocumentation(); /** * Specifies that a schema is deprecated and should be transitioned out of usage. * * @return whether or not this schema is deprecated **/ boolean deprecated() default false; /** * Provides an override for the basic type of the schema. Must be a valid type per the OpenAPI Specification. * * @return the type of this schema **/ String type() default ""; /** * Provides a list of allowable values. This field map to the enum property in the OAS schema. * * @return a list of allowed schema values */ String[] allowableValues() default {}; /** * Provides a default value. * * @return the default value of this schema */ String defaultValue() default DEFAULT_SENTINEL; /** * Provides a discriminator property value. * * @return the discriminator property */ String discriminatorProperty() default ""; /** * Provides discriminator mapping values. * * @return the discriminator mappings */ DiscriminatorMapping[] discriminatorMapping() default {}; /** * Allows schema to be marked as hidden. * * @return whether or not this schema is hidden */ boolean hidden() default false; /** * Allows enums to be resolved as a reference to a scheme added to components section. * * @since 2.1.0 * @return whether or not this must be resolved as a reference */ boolean enumAsRef() default false; /** * An array of the sub types inheriting from this model. */ Class[] subTypes() default {}; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * List of optional items positionally defines before normal items. * @return optional array of items */ Class[] prefixItems() default {}; /** * List of schema types * * @since 2.2.12 / OpenAPI 3.1 * @return array of types */ @OpenAPI31 String[] types() default {}; /** * @since 2.2.12 / OpenAPI 3.1 * * OAS 3.1 version of `exclusiveMaximum`, accepting a numeric value * * @return the exclusive maximum value for this schema **/ @OpenAPI31 int exclusiveMaximumValue() default 0; /** * Provides an exclusive minimum for a expressing exclusive range. * * @since 2.2.12 / OpenAPI 3.1 * @return an exclusive minimum. */ @OpenAPI31 int exclusiveMinimumValue() default 0; /** * Specifies contains constrictions expressions. * @return contains expression. */ @OpenAPI31 Class contains() default Void.class; /** * Provides the $id related to this schema. * * @since 2.2.12 / OpenAPI 3.1 * @return the $id of schema */ @OpenAPI31 String $id() default ""; /** * Provides Json Schema dialect where the schema is valid. * * @since 2.2.12 / OpenAPI 3.1 * @return json schema dialect */ @OpenAPI31 String $schema() default ""; /** * Provides the $anchor related to schema * * @since 2.2.12 / OpenAPI 3.1 * @return $anchor schema */ @OpenAPI31 String $anchor() default ""; /** * Provides the $vocabulary related to schema * * @since 2.2.14 / OpenAPI 3.1 * @return $vocabulary schema */ @OpenAPI31 String $vocabulary() default ""; /** * Provides the $dynamicAnchor related to schema * * @since 2.2.14 / OpenAPI 3.1 * @return $dynamicAnchor schema */ @OpenAPI31 String $dynamicAnchor() default ""; /** * Provides the $dynamicRef related to schema * * @since 2.2.32 / OpenAPI 3.1 * @return $dynamicRef schema */ @OpenAPI31 String $dynamicRef() default ""; /** * Provides the content encoding related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return content encoding */ @OpenAPI31 String contentEncoding() default ""; /** * Provides the content media type related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return content media type */ @OpenAPI31 String contentMediaType() default ""; /** * Provides the content schema related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return content schema */ @OpenAPI31 Class contentSchema() default Void.class; /** * Provides property names related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return property names */ @OpenAPI31 Class propertyNames() default Void.class; /** * Provides max contains related to this schema * @return max contains */ @OpenAPI31 int maxContains() default Integer.MAX_VALUE; /** * Provides min contains related to this schema * @return min contains */ @OpenAPI31 int minContains() default 0; /** * Provides a list of additional items * @return additional items */ Class additionalItems() default Void.class; /** * Provides a list of unevaluated items * @return unevaluated items */ Class unevaluatedItems() default Void.class; /** * Provides the if sub schema related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return if sub schema */ @OpenAPI31 Class _if() default Void.class; /** * Provides the else sub schema related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return else sub schema */ @OpenAPI31 Class _else() default Void.class; /** * Provides the then sub schema related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return then sub schema */ @OpenAPI31 Class then() default Void.class; /** * Provides $comment related to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return $comment related to schema */ @OpenAPI31 String $comment() default ""; /** * Provides a list of examples related to this schema * @return list of examples */ Class[] exampleClasses() default {}; /** * Allows to specify the additionalProperties value * * AdditionalPropertiesValue.TRUE: set to TRUE * AdditionalPropertiesValue.FALSE: set to FALSE * AdditionalPropertiesValue.USE_ADDITIONAL_PROPERTIES_ANNOTATION: resolve from @Content.additionalPropertiesSchema * or @Schema.additionalPropertiesSchema * * @since 2.2.0 * @return the accessMode for this schema (property) * */ AdditionalPropertiesValue additionalProperties() default AdditionalPropertiesValue.USE_ADDITIONAL_PROPERTIES_ANNOTATION; enum AccessMode { AUTO, READ_ONLY, WRITE_ONLY, READ_WRITE; } enum AdditionalPropertiesValue { TRUE, FALSE, USE_ADDITIONAL_PROPERTIES_ANNOTATION; } enum RequiredMode { AUTO, REQUIRED, NOT_REQUIRED; } enum SchemaResolution { AUTO, DEFAULT, INLINE, ALL_OF, ALL_OF_REF; } /** * Allows to specify the dependentRequired value ** * @since 2.2.12 / OpenAPI 3.1 * @return the list of DependentRequire annotations * */ @OpenAPI31 DependentRequired[] dependentRequiredMap() default {}; /** * Allows to specify the dependentSchemas value providing a Class to be resolved into a Schema * * @since 2.2.12 / OpenAPI 3.1 * @return the list of dependentSchemas annotations * */ @OpenAPI31 StringToClassMapItem[] dependentSchemas() default {}; /** * Provides pattern properties to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return pattern properties */ @OpenAPI31 StringToClassMapItem[] patternProperties() default {}; /** * Provides properties related to this schema * * @return schema properties */ StringToClassMapItem[] properties() default {}; /** * Provides unevaluated properties to this schema * * @since 2.2.12 / OpenAPI 3.1 * @return unevaluated properties */ @OpenAPI31 Class unevaluatedProperties() default Void.class; Class additionalPropertiesSchema() default Void.class; /** * Provides an array of examples of the schema. When associated with a specific media type, the example string shall be parsed by the consumer to be treated as an object or an array. * * @return an array of examples of this schema **/ @OpenAPI31 String[] examples() default {}; /** * Provides value restricted to this schema. * * @since 2.2.12 / OpenAPI 3.1 * @return const value */ @OpenAPI31 String _const() default ""; /** * Allows to specify the schema resolution mode for object schemas * * SchemaResolution.DEFAULT: bundled into components/schemas, $ref with no siblings * SchemaResolution.INLINE: inline schema, no $ref * SchemaResolution.ALL_OF: bundled into components/schemas, $ref and any context annotation resolution into allOf * SchemaResolution.ALL_OF_REF: bundled into components/schemas, $ref into allOf, context annotation resolution into root * * @return the schema resolution mode for this schema * */ SchemaResolution schemaResolution() default SchemaResolution.AUTO; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/SchemaProperties.java ================================================ package io.swagger.v3.oas.annotations.media; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; /** * Container for repeatable {@link SchemaProperty} annotation * * @see SchemaProperty */ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface SchemaProperties { /** * An array of SchemaProperty annotations * * @return the array of the SchemaProperty **/ SchemaProperty[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/SchemaProperty.java ================================================ package io.swagger.v3.oas.annotations.media; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; /** * The annotation may be used to define properties for an Object Schema * * @see Schema * * @since 2.1.8 **/ @Target({FIELD, METHOD, PARAMETER, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Repeatable(SchemaProperties.class) public @interface SchemaProperty { /** * The name. * * @return the name **/ String name() default ""; /** * The schema of the property. * * @return the schema **/ Schema schema() default @Schema(); /** * The schema of the array. * * @return the schema of the array */ ArraySchema array() default @ArraySchema(); } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/parameters/RequestBody.java ================================================ package io.swagger.v3.oas.annotations.parameters; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.media.Content; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; /** * The annotation may be used on a method parameter to define it as the Request Body of the operation, and/or to define * additional properties for such request body. * * @see Request Body (OpenAPI specification) * @see io.swagger.v3.oas.annotations.Parameter * @see Content **/ @Target({METHOD, PARAMETER, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface RequestBody { /** * A brief description of the request body. * * @return description of the request body **/ String description() default ""; /** * The content of the request body. * * @return array of content **/ Content[] content() default {}; /** * Determines if the request body is required in the request. Defaults to false. * * @return boolean **/ boolean required() default false; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * A reference to a RequestBody defined in components RequestBodies. * * @since 2.0.3 * @return the reference **/ String ref() default ""; /** * Set to true to resolve the request body schema from parameter type * * @since 2.2.15 **/ boolean useParameterTypeSchema() default false; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/parameters/ValidatedParameter.java ================================================ package io.swagger.v3.oas.annotations.parameters; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Variant of JSR-303's jakarta.validation.Valid, supporting the * specification of validation groups. **/ @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface ValidatedParameter { Class[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/responses/ApiResponse.java ================================================ package io.swagger.v3.oas.annotations.responses; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.media.Content; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; /** * The annotation may be used at method level or as field of {@link io.swagger.v3.oas.annotations.Operation} to define one or more responses of the * Operation. * *

swagger-jaxrs2 reader engine considers this annotation along with method return type and context as input to * resolve the OpenAPI Operation responses.

* * @see Response (OpenAPI specification) * @see io.swagger.v3.oas.annotations.Operation **/ @Target({METHOD, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Repeatable(ApiResponses.class) public @interface ApiResponse { /** * A short description of the response. * * @return description of the response **/ String description() default ""; /** * The HTTP response code, or 'default', for the supplied response. May only have 1 default entry. * * @return response code **/ String responseCode() default "default"; /** * An array of response headers. Allows additional information to be included with response. * * @return array of headers **/ Header[] headers() default {}; /** * An array of operation links that can be followed from the response. * * @return array of links **/ Link[] links() default {}; /** * An array containing descriptions of potential response payloads, for different media types. * * @return array of content **/ Content[] content() default {}; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * A reference to a response defined in components responses. * * @since 2.0.3 * @return the reference **/ String ref() default ""; /** * Set to true to resolve the response schema from method return type * * @since 2.2.0 **/ boolean useReturnTypeSchema() default false; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/responses/ApiResponses.java ================================================ package io.swagger.v3.oas.annotations.responses; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; /** * Container for repeatable {@link ApiResponse} annotation * * @see ApiResponse */ @Target({METHOD, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface ApiResponses { /** * An array of ApiResponse annotations * * @return the array of the ApiResponse **/ ApiResponse[] value() default {}; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/responses/FailedApiResponse.java ================================================ package io.swagger.v3.oas.annotations.responses; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.media.Content; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * A meta-annotation that bundles common error response definitions for API operations. *

* Includes default definitions for: *

    *
  • 400 Bad Request
  • *
  • 401 Unauthorized
  • *
  • 403 Forbidden
  • *
  • 404 Not Found
  • *
  • 429 Too Many Requests
  • *
  • 500 Internal Server Error
  • *
  • 503 Service Unavailable
  • *
* Can be used at type level to apply to all operations in a controller, * or at method level for individual operations. * * @see ApiResponse * @see ApiResponses * @since 2.2.32 */ @Target({ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content) @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content) @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content) @ApiResponse(responseCode = "404", description = "Not Found", content = @Content) @ApiResponse(responseCode = "429", description = "Too Many Requests", content = @Content) @ApiResponse(responseCode = "500", description = "Internal Server Error", content = @Content) @ApiResponse(responseCode = "503", description = "Service Unavailable", content = @Content) public @interface FailedApiResponse { /** * A reference to a response definition in components responses. * * @return the reference * @since 2.2.32 */ String ref() default ""; /** * The list of optional extensions. * * @return an optional array of extensions * @since 2.2.32 */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/security/OAuthFlow.java ================================================ package io.swagger.v3.oas.annotations.security; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Configuration details for a supported OAuth Flow. **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface OAuthFlow { /** * The authorization URL to be used for this flow. This must be in the form of a URL. Applies to oauth2 ("implicit", "authorizationCode") type. * * @return the authorization url **/ String authorizationUrl() default ""; /** * The token URL to be used for this flow. This must be in the form of a URL. Applies to oauth2 ("password", "clientCredentials", "authorizationCode") type. * * @return the token url **/ String tokenUrl() default ""; /** * The URL to be used for obtaining refresh tokens. This must be in the form of a URL. Applies to oauth2 type. * * @return the refresh url **/ String refreshUrl() default ""; /** * The available scopes for the OAuth2 security scheme. Applies to oauth2 type. * * @return array of scopes **/ OAuthScope[] scopes() default {}; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/security/OAuthFlows.java ================================================ package io.swagger.v3.oas.annotations.security; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Allows configuration of the supported OAuth Flows. **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface OAuthFlows { /** * Configuration for the OAuth Implicit flow. * * @return OAuthFlow implicit **/ OAuthFlow implicit() default @OAuthFlow(); /** * Configuration for the OAuth Resource Owner Password flow. * * @return OAuthFlow password **/ OAuthFlow password() default @OAuthFlow(); /** * Configuration for the OAuth Client Credentials flow. * * @return OAuthFlow clientCredentials **/ OAuthFlow clientCredentials() default @OAuthFlow(); /** * Configuration for the OAuth Authorization Code flow. * * @return OAuthFloe authorizationCode **/ OAuthFlow authorizationCode() default @OAuthFlow(); /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/security/OAuthScope.java ================================================ package io.swagger.v3.oas.annotations.security; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Represents an OAuth scope. **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface OAuthScope { /** * Name of the scope. * * @return String name */ String name() default ""; /** * Short description of the scope. * * @return String description */ String description() default ""; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/security/SecurityRequirement.java ================================================ package io.swagger.v3.oas.annotations.security; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.METHOD; /** * The annotation may be applied at class or method level, or in {@link io.swagger.v3.oas.annotations.Operation#security()} to define security requirements for the * single operation (when applied at method level) or for all operations of a class (when applied at class level). *

It can also be used in {@link io.swagger.v3.oas.annotations.OpenAPIDefinition#security()} to define spec level security.

*

{@link SecurityRequirement#combine()} can be used to define multiple security requirements at the same time, requiring each one of them. * If only one of multiple security schemes is required, use multiple {@link SecurityRequirement} annotations.

* * @see Security Requirement (OpenAPI specification) * @see io.swagger.v3.oas.annotations.OpenAPIDefinition * @see io.swagger.v3.oas.annotations.Operation **/ @Target({METHOD, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Repeatable(SecurityRequirements.class) @Inherited public @interface SecurityRequirement { /** * This name must correspond to a declared SecurityRequirement. *

Exactly one of this and {@link #combine()} must be set.

* * @return String name */ String name() default ""; /** * If the security scheme is of type "oauth2" or "openIdConnect", then the value is a list of scope names required for the execution. * For other security scheme types, the array must be empty. * * @return String array of scopes */ String[] scopes() default {}; /** * If multiple requirements apply at the same time, use this value instead of {@link #name()} and {@link #scopes()}. * If any one of multiple security schemes is required, use multiple {@link SecurityRequirement} annotations instead. *

Exactly one of this and {@link #name()} must be set.

* * @return SecurityRequirementEntry array of requirements */ SecurityRequirementEntry[] combine() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/security/SecurityRequirementEntry.java ================================================ package io.swagger.v3.oas.annotations.security; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * The annotation may be applied in {@link SecurityRequirement#combine()} to define combined security requirements for the * single operation. * * @see Security Requirement (OpenAPI specification) * @see io.swagger.v3.oas.annotations.security.SecurityRequirement **/ @Target({ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface SecurityRequirementEntry { /** * This name must correspond to a declared SecurityRequirement. * * @return String name */ String name(); /** * If the security scheme is of type "oauth2" or "openIdConnect", then the value is a list of scope names required for the execution. * For other security scheme types, the array must be empty. * * @return String array of scopes */ String[] scopes() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/security/SecurityRequirements.java ================================================ package io.swagger.v3.oas.annotations.security; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.METHOD; /** * Container for repeatable {@link SecurityRequirement} annotation * * @see SecurityRequirement */ @Target({METHOD, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface SecurityRequirements { /** * An array of SecurityRequirement annotations * * @return the array of the SecurityRequirement **/ SecurityRequirement[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/security/SecurityScheme.java ================================================ package io.swagger.v3.oas.annotations.security; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; /** * The annotation may be used at class level (also on multiple classes) to add securitySchemes to spec * components section. * * @see Security Scheme (OpenAPI specification) * @see Components (OpenAPI specification) **/ @Target({TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Repeatable(SecuritySchemes.class) @Inherited public @interface SecurityScheme { /** * The type of the security scheme. Valid values are "apiKey", "http", "oauth2", "openIdConnect". * * @return String type **/ SecuritySchemeType type(); /** * The name identifying this security scheme * * @return String name **/ String name() default ""; /** * A short description for security scheme. CommonMark syntax can be used for rich text representation. * * @return String description **/ String description() default ""; /** * The name of the header or query parameter to be used. Applies to apiKey type. * Maps to "name" property of Security Scheme (OpenAPI specification) * * @return String paramName **/ String paramName() default ""; /** * The location of the API key. Valid values are "query" or "header". Applies to apiKey type. * * @return String in **/ SecuritySchemeIn in() default SecuritySchemeIn.DEFAULT; /** * The name of the HTTP Authorization scheme to be used in the Authorization header as defined in RFC 7235. Applies to http type. * * @return String scheme **/ String scheme() default ""; /** * A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an * authorization server, so this information is primarily for documentation purposes. Applies to http ("bearer") type. * * @return String bearerFormat **/ String bearerFormat() default ""; /** * Required. An object containing configuration information for the flow types supported. Applies to oauth2 type. * * @return OAuthFlows flows **/ OAuthFlows flows() default @OAuthFlows; /** * Required. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of a URL. Applies to openIdConnect. * * @return String openIdConnectUrl **/ String openIdConnectUrl() default ""; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; /** * A reference to a SecurityScheme defined in components securitySchemes. * * @since 2.0.3 * @return the reference **/ String ref() default ""; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/security/SecuritySchemes.java ================================================ package io.swagger.v3.oas.annotations.security; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; /** * Container for repeatable {@link SecurityScheme} annotation * * @see SecurityScheme */ @Target({TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface SecuritySchemes { /** * An array of SecurityScheme annotations * * @return the array of the SecurityScheme **/ SecurityScheme[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/servers/Server.java ================================================ package io.swagger.v3.oas.annotations.servers; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.METHOD; /** * The annotation may be applied at class or method level, or in {@link io.swagger.v3.oas.annotations.Operation#servers()} to define servers for the * single operation (when applied at method level) or for all operations of a class (when applied at class level). *

It can also be used in {@link io.swagger.v3.oas.annotations.OpenAPIDefinition#servers()} to define spec level servers.

* * @see Server (OpenAPI specification) * @see io.swagger.v3.oas.annotations.OpenAPIDefinition * @see io.swagger.v3.oas.annotations.Operation **/ @Target({METHOD, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Repeatable(Servers.class) @Inherited public @interface Server { /** * Required. A URL to the target host. * This URL supports Server Variables and may be relative, to indicate that the host location is relative to the location where the * OpenAPI definition is being served. Variable substitutions will be made when a variable is named in {brackets}. * * @return String url **/ String url() default ""; /** * An optional string describing the host designated by the URL. CommonMark syntax MAY be used for rich text representation. * * @return String description **/ String description() default ""; /** * An array of variables used for substitution in the server's URL template. * * @return array of ServerVariables **/ ServerVariable[] variables() default {}; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/servers/ServerVariable.java ================================================ package io.swagger.v3.oas.annotations.servers; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * An object representing a Server Variable for server URL template substitution. **/ @Target({}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface ServerVariable { /** * Required. The name of this variable. * * @return String name **/ String name(); /** * An array of allowable values for this variable. This field map to the enum property in the OAS schema. * * @return String array of allowableValues **/ String[] allowableValues() default ""; /** * Required. The default value of this variable. * * @return String defaultValue **/ String defaultValue(); /** * An optional description for the server variable. * * @return String description **/ String description() default ""; /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/servers/Servers.java ================================================ package io.swagger.v3.oas.annotations.servers; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.METHOD; /** * Container for repeatable {@link Server} annotation * * @see Server */ @Target({METHOD, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Servers { /** * An array of Server Objects which is used to provide connectivity information to a target server. * * @return the servers used for this API */ Server[] value() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/tags/Tag.java ================================================ package io.swagger.v3.oas.annotations.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.extensions.Extension; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.METHOD; /** * The annotation may be applied at class or method level, or in {@link io.swagger.v3.oas.annotations.Operation#tags()} to define tags for the * single operation (when applied at method level) or for all operations of a class (when applied at class level). *

It can also be used in {@link io.swagger.v3.oas.annotations.OpenAPIDefinition#tags()} to define spec level tags.

*

When applied at method or class level, if only a name is provided, the tag will be added to operation only; * if additional fields are also defined, like description or externalDocs, the Tag will also be added to openAPI.tags * field

* * @see Tag (OpenAPI specification) * @see io.swagger.v3.oas.annotations.OpenAPIDefinition **/ @Target({METHOD, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Repeatable(Tags.class) @Inherited public @interface Tag { /** * The name of this tag. * * @return the name of this tag */ String name(); /** * A short description for this tag. * * @return the description of this tag */ String description() default ""; /** * Additional external documentation for this tag. * * @return the external documentation for this tag */ ExternalDocumentation externalDocs() default @ExternalDocumentation(); /** * The list of optional extensions * * @return an optional array of extensions */ Extension[] extensions() default {}; } ================================================ FILE: modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/tags/Tags.java ================================================ package io.swagger.v3.oas.annotations.tags; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.METHOD; /** * Container for repeatable {@link Tag} annotation * * @see Tag */ @Target({METHOD, TYPE, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Tags { /** * An array of Tag annotation objects which hold metadata for the API * * @return array of Tags */ Tag[] value() default {}; } ================================================ FILE: modules/swagger-core/pom.xml ================================================ io.swagger.core.v3 swagger-project 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-core swagger-core swagger-core src/main/java install biz.aQute.bnd bnd-maven-plugin Import-Package: \ javax.validation.constraints;version="[1.1,3)", \ javax.xml.bind.annotation;version="[2.2,3)", \ * org.apache.maven.plugins maven-jar-plugin 3.3.0 default-jar ${project.build.outputDirectory}/META-INF/MANIFEST.MF io.swagger.v3.core test-jar jakarta.xml.bind jakarta.xml.bind-api 2.3.3 org.apache.commons commons-lang3 org.slf4j slf4j-api com.fasterxml.jackson.core jackson-annotations com.fasterxml.jackson.core jackson-databind com.fasterxml.jackson.dataformat jackson-dataformat-yaml com.fasterxml.jackson.datatype jackson-datatype-jsr310 io.swagger.core.v3 swagger-annotations ${project.parent.version} org.yaml snakeyaml ${snakeyaml-version} io.swagger.core.v3 swagger-models ${project.parent.version} joda-time joda-time test com.google.guava guava test org.joda joda-convert test ch.qos.logback logback-classic provided ch.qos.logback logback-core provided jakarta.validation jakarta.validation-api ${validation-api-version} org.testng testng test commons-io commons-io jakarta.ws.rs jakarta.ws.rs-api ${jakarta-ws-rs-api-version} test jakarta.inject jakarta.inject-api 1.0.5 test 2.0.2 2.1.6 0.60 0.0 3 ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/converter/AnnotatedType.java ================================================ package io.swagger.v3.core.converter; import com.fasterxml.jackson.annotation.JsonView; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.media.Schema; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; public class AnnotatedType { private Type type; private String name; private Schema parent; private Function jsonUnwrappedHandler; private boolean skipOverride; private boolean schemaProperty; private Annotation[] ctxAnnotations; private boolean resolveAsRef; private boolean resolveEnumAsRef; private JsonView jsonViewAnnotation; private boolean includePropertiesWithoutJSONView = true; private boolean skipSchemaName; private boolean skipJsonIdentity; private String propertyName; private boolean isSubtype; private Components components; public AnnotatedType() { } public AnnotatedType(Type type) { this.type = type; } public boolean isSkipOverride() { return skipOverride; } public void setSkipOverride(boolean skipOverride) { this.skipOverride = skipOverride; } public AnnotatedType skipOverride(boolean skipOverride) { this.skipOverride = skipOverride; return this; } public boolean isSkipJsonIdentity() { return skipJsonIdentity; } public void setSkipJsonIdentity(boolean skipJsonIdentity) { this.skipJsonIdentity = skipJsonIdentity; } public AnnotatedType skipJsonIdentity(boolean skipJsonIdentity) { this.skipJsonIdentity = skipJsonIdentity; return this; } public boolean isSkipSchemaName() { return skipSchemaName; } public void setSkipSchemaName(boolean skipSchemaName) { this.skipSchemaName = skipSchemaName; } public AnnotatedType skipSchemaName(boolean skipSchemaName) { this.skipSchemaName = skipSchemaName; return this; } public boolean isResolveAsRef() { return resolveAsRef; } public void setResolveAsRef(boolean resolveAsRef) { this.resolveAsRef = resolveAsRef; } public AnnotatedType resolveAsRef(boolean resolveAsRef) { this.resolveAsRef = resolveAsRef; return this; } public boolean isResolveEnumAsRef() { return resolveEnumAsRef; } public void setResolveEnumAsRef(boolean resolveEnumAsRef) { this.resolveEnumAsRef = resolveEnumAsRef; } public AnnotatedType resolveEnumAsRef(boolean resolveEnumAsRef) { this.resolveEnumAsRef = resolveEnumAsRef; return this; } public boolean isSchemaProperty() { return schemaProperty; } public void setSchemaProperty(boolean schemaProperty) { this.schemaProperty = schemaProperty; } public AnnotatedType schemaProperty(boolean schemaProperty) { this.schemaProperty = schemaProperty; return this; } public Function getJsonUnwrappedHandler() { return jsonUnwrappedHandler; } public void setJsonUnwrappedHandler(Function jsonUnwrappedHandler) { this.jsonUnwrappedHandler = jsonUnwrappedHandler; } public AnnotatedType jsonUnwrappedHandler(Function jsonUnwrappedHandler) { this.jsonUnwrappedHandler = jsonUnwrappedHandler; return this; } public Schema getParent() { return parent; } public void setParent(Schema parent) { this.parent = parent; } public AnnotatedType parent(Schema parent) { this.parent = parent; return this; } public String getName() { return name; } public void setName(String name) { this.name = name; } public AnnotatedType name(String name) { this.name = name; return this; } public Annotation[] getCtxAnnotations() { return ctxAnnotations == null ? null : Arrays.copyOf(ctxAnnotations, ctxAnnotations.length); } public void setCtxAnnotations(Annotation[] ctxAnnotations) { this.ctxAnnotations = ctxAnnotations == null ? null : Arrays.copyOf(ctxAnnotations, ctxAnnotations.length); } public AnnotatedType ctxAnnotations(Annotation[] ctxAnnotations) { setCtxAnnotations(ctxAnnotations); return this; } public Components getComponents() { return components; } public void setComponents(Components components) { this.components = components; } public AnnotatedType components(Components components) { setComponents(components); return this; } public Type getType() { return type; } public void setType(Type type) { this.type = type; } public AnnotatedType type(Type type) { setType(type); return this; } public JsonView getJsonViewAnnotation() { return jsonViewAnnotation; } public void setJsonViewAnnotation(JsonView jsonViewAnnotation) { this.jsonViewAnnotation = jsonViewAnnotation; } public AnnotatedType jsonViewAnnotation(JsonView jsonViewAnnotation) { this.jsonViewAnnotation = jsonViewAnnotation; return this; } public boolean isIncludePropertiesWithoutJSONView() { return includePropertiesWithoutJSONView; } public void setIncludePropertiesWithoutJSONView(boolean includePropertiesWithoutJSONView) { this.includePropertiesWithoutJSONView = includePropertiesWithoutJSONView; } public AnnotatedType includePropertiesWithoutJSONView(boolean includePropertiesWithoutJSONView) { this.includePropertiesWithoutJSONView = includePropertiesWithoutJSONView; return this; } /** * @since 2.0.4 */ public String getPropertyName() { return propertyName; } /** * @since 2.0.4 */ public void setPropertyName(String propertyName) { this.propertyName = propertyName; } /** * @since 2.0.4 */ public AnnotatedType propertyName(String propertyName) { this.propertyName = propertyName; return this; } public boolean isSubtype() { return isSubtype; } public void setSubtype(boolean isSubtype) { this.isSubtype = isSubtype; } public AnnotatedType subtype(boolean isSubtype) { this.isSubtype = isSubtype; return this; } private List getProcessedAnnotations(Annotation[] annotations) { if (annotations == null || annotations.length == 0) { return new ArrayList<>(); } return Arrays.stream(annotations) .filter(a -> { String pkg = a.annotationType().getPackage().getName(); return !pkg.startsWith("java.") && !pkg.startsWith("jdk.") && !pkg.startsWith("sun."); }) .sorted(Comparator.comparing(a -> a.annotationType().getName())) .collect(Collectors.toList()); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof AnnotatedType)) return false; AnnotatedType that = (AnnotatedType) o; List thisAnnotatinons = getProcessedAnnotations(this.ctxAnnotations); List thatAnnotatinons = getProcessedAnnotations(that.ctxAnnotations); return includePropertiesWithoutJSONView == that.includePropertiesWithoutJSONView && schemaProperty == that.schemaProperty && isSubtype == that.isSubtype && Objects.equals(type, that.type) && Objects.equals(thisAnnotatinons, thatAnnotatinons) && Objects.equals(jsonViewAnnotation, that.jsonViewAnnotation) && (!schemaProperty || Objects.equals(propertyName, that.propertyName)); } @Override public int hashCode() { List processedAnnotations = getProcessedAnnotations(this.ctxAnnotations); return Objects.hash(type, jsonViewAnnotation, includePropertiesWithoutJSONView, processedAnnotations, schemaProperty, isSubtype, schemaProperty ? propertyName : null); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverter.java ================================================ package io.swagger.v3.core.converter; import io.swagger.v3.oas.models.media.Schema; import java.util.Iterator; public interface ModelConverter { /** * @param type * @param context * @param chain the chain of model converters to try if this implementation cannot process * @return null if this ModelConverter cannot convert the given Type */ Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain); default boolean isOpenapi31() { return false; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverterContext.java ================================================ package io.swagger.v3.core.converter; import io.swagger.v3.oas.models.media.Schema; import java.lang.reflect.Type; import java.util.Iterator; import java.util.Map; public interface ModelConverterContext { /** * needs to be called whenever a Model is defined which can be referenced from another * Model or Property * * @param name the name of the model * @param model the Model */ void defineModel(String name, Schema model); /** * needs to be called whenever a Schema is defined which can be referenced from another * Model or Property * * @param name the name of the model * @param model the Model * @param type the AnnotatedType * @param prevName the (optional) previous name */ void defineModel(String name, Schema model, AnnotatedType type, String prevName); /** * needs to be called whenever a Schema is defined which can be referenced from another * Model or Property * * @param name the name of the model * @param model the Model * @param type the Type * @param prevName the (optional) previous name */ void defineModel(String name, Schema model, Type type, String prevName); /** * @param type The Schema * @return a Model representation of the Class. Any referenced models will be defined already. */ Schema resolve(AnnotatedType type); Map getDefinedModels(); /** * @return an Iterator of ModelConverters. This iterator is not reused */ public Iterator getConverters(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverterContextImpl.java ================================================ package io.swagger.v3.core.converter; import io.swagger.v3.core.util.ReferenceTypeUtils; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class ModelConverterContextImpl implements ModelConverterContext { private static final Logger LOGGER = LoggerFactory.getLogger(ModelConverterContextImpl.class); private final List converters; private final Map modelByName; private final HashMap modelByType; private final Set processedTypes; public ModelConverterContextImpl(List converters) { this.converters = converters; modelByName = new TreeMap<>(); modelByType = new HashMap<>(); processedTypes = new HashSet<>(); } public ModelConverterContextImpl(ModelConverter converter) { this(new ArrayList()); converters.add(converter); } @Override public Iterator getConverters() { return converters.iterator(); } @Override public void defineModel(String name, Schema model) { AnnotatedType aType = null; defineModel(name, model, aType, null); } @Override public void defineModel(String name, Schema model, Type type, String prevName) { defineModel(name, model, new AnnotatedType().type(type), prevName); } @Override public void defineModel(String name, Schema model, AnnotatedType type, String prevName) { if (LOGGER.isTraceEnabled()) { LOGGER.trace(String.format("defineModel %s %s", name, model)); } modelByName.put(name, model); if (StringUtils.isNotBlank(prevName) && !prevName.equals(name)) { modelByName.remove(prevName); } if (type != null && type.getType() != null) { modelByType.put(type, model); } } @Override public Map getDefinedModels() { return Collections.unmodifiableMap(modelByName); } @Override public Schema resolve(AnnotatedType type) { AnnotatedType aType = ReferenceTypeUtils.unwrapReference(type); if (aType != null) { return resolve(aType); } if (processedTypes.contains(type)) { return modelByType.get(type); } else { processedTypes.add(type); } if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("resolve %s", type.getType())); } Iterator converters = this.getConverters(); Schema resolved = null; if (converters.hasNext()) { ModelConverter converter = converters.next(); LOGGER.trace("trying extension {}", converter); resolved = converter.resolve(type, this, converters); } if (resolved != null) { modelByType.put(type, resolved); Schema resolvedImpl = resolved; if (resolvedImpl.getName() != null) { modelByName.put(resolvedImpl.getName(), resolved); } } else { processedTypes.remove(type); } return resolved; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ModelConverters.java ================================================ package io.swagger.v3.core.converter; import com.fasterxml.jackson.databind.type.TypeFactory; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.oas.models.media.Schema; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Type; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; public class ModelConverters { private static ModelConverters SINGLETON = null; private static ModelConverters SINGLETON31 = null; static Logger LOGGER = LoggerFactory.getLogger(ModelConverters.class); private final List converters; private final Set skippedPackages = new HashSet<>(); private final Set skippedClasses = new HashSet<>(); public ModelConverters() { converters = new CopyOnWriteArrayList<>(); converters.add(new ModelResolver(Json.mapper())); } public ModelConverters(boolean openapi31) { converters = new CopyOnWriteArrayList<>(); if (openapi31) { converters.add(new ModelResolver(Json31.mapper()).openapi31(true)); } else { converters.add(new ModelResolver(Json.mapper())); } } public ModelConverters(boolean openapi31, Schema.SchemaResolution schemaResolution) { converters = new CopyOnWriteArrayList<>(); if (openapi31) { converters.add(new ModelResolver(Json31.mapper()).openapi31(true).schemaResolution(schemaResolution)); } else { converters.add(new ModelResolver(Json.mapper()).schemaResolution(schemaResolution)); } } public ModelConverters(Configuration configuration) { converters = new CopyOnWriteArrayList<>(); boolean openapi31 =configuration != null && configuration.isOpenAPI31() != null && configuration.isOpenAPI31(); if (openapi31) { converters.add(new ModelResolver(Json31.mapper()).configuration(configuration)); } else { converters.add(new ModelResolver(Json.mapper()).configuration(configuration)); } } public Set getSkippedPackages() { return skippedPackages; } public static ModelConverters getInstance(boolean openapi31) { if (openapi31) { if (SINGLETON31 == null) { SINGLETON31 = new ModelConverters(openapi31); init(SINGLETON31); } return SINGLETON31; } if (SINGLETON == null) { SINGLETON = new ModelConverters(openapi31); init(SINGLETON); } return SINGLETON; } public static void reset() { synchronized (ModelConverters.class) { SINGLETON = null; SINGLETON31 = null; } } public static ModelConverters getInstance(boolean openapi31, Schema.SchemaResolution schemaResolution) { synchronized (ModelConverters.class) { if (openapi31) { if (SINGLETON31 == null) { boolean applySchemaResolution = Boolean.parseBoolean(System.getProperty(Schema.APPLY_SCHEMA_RESOLUTION_PROPERTY, "false")) || Boolean.parseBoolean(System.getenv(Schema.APPLY_SCHEMA_RESOLUTION_PROPERTY)); SINGLETON31 = new ModelConverters(openapi31, applySchemaResolution ? schemaResolution : Schema.SchemaResolution.DEFAULT); init(SINGLETON31); } return SINGLETON31; } if (SINGLETON == null) { SINGLETON = new ModelConverters(openapi31, schemaResolution); init(SINGLETON); } return SINGLETON; } } public static ModelConverters getInstance(Configuration configuration) { synchronized (ModelConverters.class) { boolean openapi31 = configuration != null && configuration.isOpenAPI31() != null && configuration.isOpenAPI31(); if (openapi31) { if (SINGLETON31 == null) { boolean applySchemaResolution = Boolean.parseBoolean(System.getProperty(Schema.APPLY_SCHEMA_RESOLUTION_PROPERTY, "false")) || Boolean.parseBoolean(System.getenv(Schema.APPLY_SCHEMA_RESOLUTION_PROPERTY)); if (!applySchemaResolution) { configuration.schemaResolution(Schema.SchemaResolution.DEFAULT); } SINGLETON31 = new ModelConverters(configuration); init(SINGLETON31); } return SINGLETON31; } if (SINGLETON == null) { SINGLETON = new ModelConverters(configuration); init(SINGLETON); } return SINGLETON; } } private static void init(ModelConverters converter) { converter.addPackageToSkip("java.lang"); converter.addPackageToSkip("groovy.lang"); ServiceLoader loader = ServiceLoader.load(ModelConverter.class); Iterator itr = loader.iterator(); while (itr.hasNext()) { ModelConverter ext = itr.next(); if (ext == null) { LOGGER.error("failed to load extension {}", ext); } else { converter.addConverter(ext); LOGGER.debug("adding ModelConverter: {}", ext); } } } public static ModelConverters getInstance() { return getInstance(false); } public void addConverter(ModelConverter converter) { converters.add(0, converter); } public void removeConverter(ModelConverter converter) { converters.remove(converter); } public List getConverters() { return Collections.unmodifiableList(converters); } public void addPackageToSkip(String pkg) { this.skippedPackages.add(pkg); } public void addClassToSkip(String cls) { LOGGER.warn("skipping class {}", cls); this.skippedClasses.add(cls); } public Map read(Type type) { return read(new AnnotatedType().type(type)); } public Map read(AnnotatedType type) { Map modelMap = new HashMap<>(); if (shouldProcess(type.getType())) { ModelConverterContextImpl context = new ModelConverterContextImpl( converters); Schema resolve = context.resolve(type); for (Entry entry : context.getDefinedModels() .entrySet()) { if (entry.getValue().equals(resolve)) { modelMap.put(entry.getKey(), entry.getValue()); } } } return modelMap; } public Map readAll(Type type) { return readAll(new AnnotatedType().type(type)); } public Map readAll(AnnotatedType type) { if (shouldProcess(type.getType())) { ModelConverterContextImpl context = new ModelConverterContextImpl( converters); LOGGER.debug("ModelConverters readAll from {}", type); context.resolve(type); return context.getDefinedModels(); } return new HashMap<>(); } public ResolvedSchema readAllAsResolvedSchema(Type type) { return readAllAsResolvedSchema(new AnnotatedType().type(type)); } public ResolvedSchema readAllAsResolvedSchema(AnnotatedType type) { if (shouldProcess(type.getType())) { return resolveAsResolvedSchema(type); } return null; } public ResolvedSchema resolveAsResolvedSchema(AnnotatedType type) { ModelConverterContextImpl context = new ModelConverterContextImpl( converters); ResolvedSchema resolvedSchema = new ResolvedSchema(); resolvedSchema.schema = context.resolve(type); resolvedSchema.referencedSchemas = context.getDefinedModels(); return resolvedSchema; } public boolean isRegisteredAsSkippedClass(String className) { return skippedClasses.contains(className); } private boolean shouldProcess(Type type) { final Class cls = TypeFactory.defaultInstance().constructType(type).getRawClass(); if (cls.isPrimitive()) { return false; } String className = cls.getName(); for (String packageName : skippedPackages) { if (className.startsWith(packageName)) { return false; } } return !skippedClasses.contains(className); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/converter/ResolvedSchema.java ================================================ package io.swagger.v3.core.converter; import io.swagger.v3.oas.models.media.Schema; import java.util.Map; public class ResolvedSchema { public Schema schema; public Map referencedSchemas; } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/filter/AbstractSpecFilter.java ================================================ package io.swagger.v3.core.filter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import java.util.List; import java.util.Map; import java.util.Optional; public abstract class AbstractSpecFilter implements OpenAPISpecFilter { @Override public Optional filterOpenAPI(OpenAPI openAPI, Map> params, Map cookies, Map> headers) { return Optional.of(openAPI); } @Override public Optional filterPathItem(PathItem pathItem, ApiDescription api, Map> params, Map cookies, Map> headers) { return Optional.of(pathItem); } @Override public Optional filterOperation(Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { return Optional.of(operation); } @Override public Optional filterParameter(Parameter parameter, Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { return Optional.of(parameter); } @Override public Optional filterRequestBody(RequestBody requestBody, Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { return Optional.of(requestBody); } @Override public Optional filterResponse(ApiResponse response, Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { return Optional.of(response); } @Override public Optional filterSchema(Schema schema, Map> params, Map cookies, Map> headers) { return Optional.of(schema); } @Override public Optional filterSchemaProperty(Schema property, Schema schema, String propName, Map> params, Map cookies, Map> headers) { return Optional.of(property); } @Override public boolean isRemovingUnreferencedDefinitions() { return false; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/filter/OpenAPI31SpecFilter.java ================================================ package io.swagger.v3.core.filter; import io.swagger.v3.core.util.OpenAPI30To31; import io.swagger.v3.core.util.OpenAPISchema2JsonSchema; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import java.util.List; import java.util.Map; import java.util.Optional; public class OpenAPI31SpecFilter extends AbstractSpecFilter { private OpenAPI30To31 openAPI30To31 = new OpenAPI30To31(); private OpenAPISchema2JsonSchema schema2JsonSchema = new OpenAPISchema2JsonSchema(); @Override public Optional filterOpenAPI(OpenAPI openAPI, Map> params, Map cookies, Map> headers) { openAPI30To31.process(openAPI); return Optional.of(openAPI); } @Override public Optional filterSchema(Schema schema, Map> params, Map cookies, Map> headers) { schema2JsonSchema.process(schema); return Optional.of(schema); } @Override public boolean isOpenAPI31Filter() { return true; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/filter/OpenAPISpecFilter.java ================================================ package io.swagger.v3.core.filter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import java.util.List; import java.util.Map; import java.util.Optional; public interface OpenAPISpecFilter { Optional filterOpenAPI( OpenAPI openAPI, Map> params, Map cookies, Map> headers); Optional filterPathItem( PathItem pathItem, ApiDescription api, Map> params, Map cookies, Map> headers); Optional filterOperation( Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers); Optional filterParameter( Parameter parameter, Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers); Optional filterRequestBody( RequestBody requestBody, Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers); Optional filterResponse( ApiResponse response, Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers); Optional filterSchema( Schema schema, Map> params, Map cookies, Map> headers); Optional filterSchemaProperty( Schema property, Schema schema, String propName, Map> params, Map cookies, Map> headers); boolean isRemovingUnreferencedDefinitions(); default boolean isOpenAPI31Filter() { return false; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/filter/SpecFilter.java ================================================ package io.swagger.v3.core.filter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.RefUtils; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.tags.Tag; import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; public class SpecFilter { public OpenAPI filter(OpenAPI openAPI, OpenAPISpecFilter filter, Map> params, Map cookies, Map> headers) { OpenAPI filteredOpenAPI = filterOpenAPI(filter, openAPI, params, cookies, headers); if (filteredOpenAPI == null) { return filteredOpenAPI; } OpenAPI clone = new OpenAPI(); clone.info(filteredOpenAPI.getInfo()); clone.openapi(filteredOpenAPI.getOpenapi()); clone.jsonSchemaDialect(filteredOpenAPI.getJsonSchemaDialect()); clone.setSpecVersion(filteredOpenAPI.getSpecVersion()); clone.setExtensions(filteredOpenAPI.getExtensions()); clone.setExternalDocs(filteredOpenAPI.getExternalDocs()); clone.setSecurity(filteredOpenAPI.getSecurity()); clone.setServers(filteredOpenAPI.getServers()); clone.tags(filteredOpenAPI.getTags() == null ? null : new ArrayList<>(openAPI.getTags())); final Set allowedTags = new HashSet<>(); final Set filteredTags = new HashSet<>(); Paths clonedPaths = new Paths(); if (filteredOpenAPI.getPaths() != null) { for (String resourcePath : filteredOpenAPI.getPaths().keySet()) { PathItem pathItem = filteredOpenAPI.getPaths().get(resourcePath); PathItem filteredPathItem = filterPathItem(filter, pathItem, resourcePath, params, cookies, headers); PathItem clonedPathItem = cloneFilteredPathItem(filter,filteredPathItem, resourcePath, params, cookies, headers, allowedTags, filteredTags); if (clonedPathItem != null) { if (!clonedPathItem.readOperations().isEmpty()) { clonedPaths.addPathItem(resourcePath, clonedPathItem); } } } clone.paths(clonedPaths); } filteredTags.removeAll(allowedTags); final List tags = clone.getTags(); if (tags != null && !filteredTags.isEmpty()) { tags.removeIf(tag -> filteredTags.contains(tag.getName())); if (clone.getTags().isEmpty()) { clone.setTags(null); } } if (filteredOpenAPI.getWebhooks() != null) { for (String resourcePath : filteredOpenAPI.getWebhooks().keySet()) { PathItem pathItem = filteredOpenAPI.getWebhooks().get(resourcePath); PathItem filteredPathItem = filterPathItem(filter, pathItem, resourcePath, params, cookies, headers); PathItem clonedPathItem = cloneFilteredPathItem(filter,filteredPathItem, resourcePath, params, cookies, headers, allowedTags, filteredTags); if (clonedPathItem != null) { if (!clonedPathItem.readOperations().isEmpty()) { clone.addWebhooks(resourcePath, clonedPathItem); } } } } if (filteredOpenAPI.getComponents() != null) { clone.components(new Components()); clone.getComponents().setSchemas(filterComponentsSchema(filter, filteredOpenAPI.getComponents().getSchemas(), params, cookies, headers)); clone.getComponents().setSecuritySchemes(filteredOpenAPI.getComponents().getSecuritySchemes()); clone.getComponents().setCallbacks(filteredOpenAPI.getComponents().getCallbacks()); clone.getComponents().setExamples(filteredOpenAPI.getComponents().getExamples()); clone.getComponents().setExtensions(filteredOpenAPI.getComponents().getExtensions()); clone.getComponents().setHeaders(filteredOpenAPI.getComponents().getHeaders()); clone.getComponents().setLinks(filteredOpenAPI.getComponents().getLinks()); clone.getComponents().setParameters(filteredOpenAPI.getComponents().getParameters()); clone.getComponents().setRequestBodies(filteredOpenAPI.getComponents().getRequestBodies()); clone.getComponents().setResponses(filteredOpenAPI.getComponents().getResponses()); clone.getComponents().setPathItems(filteredOpenAPI.getComponents().getPathItems()); } if (filter.isRemovingUnreferencedDefinitions()) { clone = removeBrokenReferenceDefinitions(clone); } return clone; } protected OpenAPI filterOpenAPI(OpenAPISpecFilter filter, OpenAPI openAPI, Map> params, Map cookies, Map> headers) { if (openAPI != null) { Optional filteredOpenAPI = filter.filterOpenAPI(openAPI, params, cookies, headers); if (filteredOpenAPI.isPresent()) { return filteredOpenAPI.get(); } } return null; } protected Operation filterOperation(OpenAPISpecFilter filter, Operation operation, String resourcePath, String key, Map> params, Map cookies, Map> headers) { if (operation != null) { ApiDescription description = new ApiDescription(resourcePath, key); Optional filteredOperation = filter.filterOperation(operation, description, params, cookies, headers); if (filteredOperation.isPresent()) { List filteredParameters = new ArrayList<>(); Operation filteredOperationGet = filteredOperation.get(); Operation clone = new Operation(); clone.setCallbacks(filteredOperationGet.getCallbacks()); clone.setDeprecated(filteredOperationGet.getDeprecated()); clone.setDescription(filteredOperationGet.getDescription()); clone.setExtensions(filteredOperationGet.getExtensions()); clone.setExternalDocs(filteredOperationGet.getExternalDocs()); clone.setOperationId(filteredOperationGet.getOperationId()); clone.setSecurity(filteredOperationGet.getSecurity()); clone.setServers(filteredOperationGet.getServers()); clone.setSummary(filteredOperationGet.getSummary()); clone.setTags(filteredOperationGet.getTags()); List parameters = filteredOperationGet.getParameters(); if (parameters != null) { for (Parameter parameter : parameters) { Parameter filteredParameter = filterParameter(filter, operation, parameter, resourcePath, key, params, cookies, headers); if (filteredParameter != null) { filteredParameters.add(filteredParameter); } } clone.setParameters(filteredParameters); } RequestBody requestBody = filteredOperation.get().getRequestBody(); if (requestBody != null) { RequestBody filteredRequestBody = filterRequestBody(filter, operation, requestBody, resourcePath, key, params, cookies, headers); clone.setRequestBody(filteredRequestBody); } ApiResponses responses = filteredOperation.get().getResponses(); ApiResponses clonedResponses = responses; if (responses != null) { responses.forEach((responseKey, response) -> { ApiResponse filteredResponse = filterResponse(filter, operation, response, resourcePath, key, params, cookies, headers); if (filteredResponse != null) { clonedResponses.addApiResponse(responseKey, filteredResponse); } }); clone.setResponses(clonedResponses); } return clone; } } return null; } protected PathItem filterPathItem(OpenAPISpecFilter filter, PathItem pathItem, String resourcePath, Map> params, Map cookies, Map> headers) { ApiDescription description = new ApiDescription(resourcePath, null); Optional filteredPathItem = filter.filterPathItem(pathItem, description, params, cookies, headers); if (filteredPathItem.isPresent()) { return filteredPathItem.get(); } return null; } protected Parameter filterParameter(OpenAPISpecFilter filter, Operation operation, Parameter parameter, String resourcePath, String key, Map> params, Map cookies, Map> headers) { if (parameter != null) { ApiDescription description = new ApiDescription(resourcePath, key); Optional filteredParameter = filter.filterParameter(parameter, operation, description, params, cookies, headers); if (filteredParameter.isPresent()) { return filteredParameter.get(); } } return null; } protected RequestBody filterRequestBody(OpenAPISpecFilter filter, Operation operation, RequestBody requestBody, String resourcePath, String key, Map> params, Map cookies, Map> headers) { if (requestBody != null) { ApiDescription description = new ApiDescription(resourcePath, key); Optional filteredRequestBody = filter.filterRequestBody(requestBody, operation, description, params, cookies, headers); if (filteredRequestBody.isPresent()) { return filteredRequestBody.get(); } } return null; } protected ApiResponse filterResponse(OpenAPISpecFilter filter, Operation operation, ApiResponse response, String resourcePath, String key, Map> params, Map cookies, Map> headers) { if (response != null) { ApiDescription description = new ApiDescription(resourcePath, key); Optional filteredResponse = filter.filterResponse(response, operation, description, params, cookies, headers); if (filteredResponse.isPresent()) { return filteredResponse.get(); } } return null; } protected Map filterComponentsSchema(OpenAPISpecFilter filter, Map schemasMap, Map> params, Map cookies, Map> headers) { if (schemasMap == null) { return null; } Map clonedComponentsSchema = new LinkedHashMap<>(); for (Map.Entry entry : schemasMap.entrySet()) { String key = entry.getKey(); Schema definition = entry.getValue(); Optional filteredDefinition = filter.filterSchema(definition, params, cookies, headers); if (filteredDefinition.isPresent()) { Map clonedProperties = new LinkedHashMap<>(); if (filteredDefinition.get().getProperties() != null) { for (Object propName : filteredDefinition.get().getProperties().keySet()) { Schema property = (Schema) filteredDefinition.get().getProperties().get(propName); if (property != null) { Optional filteredProperty = filter.filterSchemaProperty(property, definition, (String) propName, params, cookies, headers); if (filteredProperty.isPresent()) { clonedProperties.put((String) propName, filteredProperty.get()); } } } } Map clonedPatternProperties = new LinkedHashMap<>(); if (filteredDefinition.get().getPatternProperties() != null) { for (Object propName : filteredDefinition.get().getPatternProperties().keySet()) { Schema property = (Schema) filteredDefinition.get().getPatternProperties().get(propName); if (property != null) { Optional filteredProperty = filter.filterSchemaProperty(property, definition, (String) propName, params, cookies, headers); if (filteredProperty.isPresent()) { clonedPatternProperties.put((String) propName, filteredProperty.get()); } } } } try { // TODO solve this, and generally handle clone and passing references Schema clonedModel; if (filter.isOpenAPI31Filter()) { clonedModel = Json31.mapper().readValue(Json31.pretty(definition), Schema.class); } else { clonedModel = Json.mapper().readValue(Json.pretty(definition), Schema.class); } if (clonedModel.getProperties() != null) { clonedModel.getProperties().clear(); } if (!clonedProperties.isEmpty()) { clonedModel.setProperties(clonedProperties); } if(clonedModel.getPatternProperties() != null) { clonedModel.getPatternProperties().clear(); } if(!clonedPatternProperties.isEmpty()) { clonedModel.setPatternProperties(clonedPatternProperties); } clonedComponentsSchema.put(key, clonedModel); } catch (IOException e) { } } } return clonedComponentsSchema; } private void addSchemaRef(Schema schema, Set referencedDefinitions) { if (schema == null) { return; } if (!StringUtils.isBlank(schema.get$ref())) { referencedDefinitions.add(schema.get$ref()); return; } if (schema.getDiscriminator() != null && schema.getDiscriminator().getMapping() != null) { for (Map.Entry mapping: schema.getDiscriminator().getMapping().entrySet()) { referencedDefinitions.add(mapping.getValue()); } } if (schema.getProperties() != null) { for (Object propName : schema.getProperties().keySet()) { Schema property = (Schema) schema.getProperties().get(propName); addSchemaRef(property, referencedDefinitions); } } if (schema.getAdditionalProperties() instanceof Schema) { addSchemaRef((Schema)schema.getAdditionalProperties(), referencedDefinitions); } if (schema.getPatternProperties() != null) { for (Object propName : schema.getPatternProperties().keySet()) { Schema property = (Schema) schema.getPatternProperties().get(propName); addSchemaRef(property, referencedDefinitions); } } if (schema.getPropertyNames() != null) { addSchemaRef(schema.getPropertyNames(), referencedDefinitions); } if (schema instanceof ArraySchema && ((ArraySchema) schema).getItems() != null) { addSchemaRef(((ArraySchema) schema).getItems(), referencedDefinitions); } else if (schema.getTypes() != null && schema.getTypes().contains("array") && schema.getItems() != null) { addSchemaRef(schema.getItems(), referencedDefinitions); } else { List allOf = schema.getAllOf(); List anyOf = schema.getAnyOf(); List oneOf = schema.getOneOf(); if (allOf != null) { for (Schema ref : allOf) { addSchemaRef(ref, referencedDefinitions); } } if (anyOf != null) { for (Schema ref : anyOf) { addSchemaRef(ref, referencedDefinitions); } } if (oneOf != null) { for (Schema ref : oneOf) { addSchemaRef(ref, referencedDefinitions); } } } } private void addContentSchemaRef(Content content, Set referencedDefinitions) { if (content != null) { for (MediaType mediaType : content.values()) { addSchemaRef(mediaType.getSchema(), referencedDefinitions); } } } private void addPathItemSchemaRef(PathItem pathItem, Set referencedDefinitions) { if (pathItem.getParameters() != null) { for (Parameter parameter : pathItem.getParameters()) { addSchemaRef(parameter.getSchema(), referencedDefinitions); addContentSchemaRef(parameter.getContent(), referencedDefinitions); } } Map ops = pathItem.readOperationsMap(); for (Operation op : ops.values()) { if (op.getRequestBody() != null) { addRequestBodySchemaRef(op.getRequestBody(), referencedDefinitions); } if (op.getResponses() != null) { for (String keyResponses : op.getResponses().keySet()) { ApiResponse response = op.getResponses().get(keyResponses); addApiResponseSchemaRef(response, referencedDefinitions); } } if (op.getParameters() != null) { for (Parameter parameter : op.getParameters()) { addParameterSchemaRef(parameter, referencedDefinitions); } } if (op.getCallbacks() != null) { for (String keyCallback : op.getCallbacks().keySet()) { Callback callback = op.getCallbacks().get(keyCallback); addCallbackSchemaRef(callback, referencedDefinitions); } } } } private void addApiResponseSchemaRef(ApiResponse response, Set referencedDefinitions) { if (response.getHeaders() != null) { for (String keyHeaders : response.getHeaders().keySet()) { Header header = response.getHeaders().get(keyHeaders); addHeaderSchemaRef(header, referencedDefinitions); } } addContentSchemaRef(response.getContent(), referencedDefinitions); } private void addRequestBodySchemaRef(RequestBody requestBody, Set referencedDefinitions) { addContentSchemaRef(requestBody.getContent(), referencedDefinitions); } private void addParameterSchemaRef(Parameter parameter, Set referencedDefinitions) { addSchemaRef(parameter.getSchema(), referencedDefinitions); addContentSchemaRef(parameter.getContent(), referencedDefinitions); } private void addHeaderSchemaRef(Header header, Set referencedDefinitions) { addSchemaRef(header.getSchema(), referencedDefinitions); addContentSchemaRef(header.getContent(), referencedDefinitions); } private void addCallbackSchemaRef(Callback callback, Set referencedDefinitions){ for (PathItem callbackPathItem : callback.values()) { addPathItemSchemaRef(callbackPathItem, referencedDefinitions); } } private void addComponentsSchemaRef(Components components, Set referencedDefinitions){ if (components.getResponses() != null){ for (String resourcePath : components.getResponses().keySet()) { ApiResponse apiResponse = components.getResponses().get(resourcePath); addApiResponseSchemaRef(apiResponse, referencedDefinitions); } } if (components.getRequestBodies() != null){ for (String requestBody : components.getRequestBodies().keySet()) { RequestBody requestBody1 = components.getRequestBodies().get(requestBody); addRequestBodySchemaRef(requestBody1, referencedDefinitions); } } if (components.getParameters() != null){ for (String parameter : components.getParameters().keySet()) { Parameter resourceParam = components.getParameters().get(parameter); addParameterSchemaRef(resourceParam, referencedDefinitions); } } if (components.getHeaders() != null){ for (String header : components.getHeaders().keySet()) { Header resourceHeader = components.getHeaders().get(header); addHeaderSchemaRef(resourceHeader, referencedDefinitions); } } if (components.getCallbacks() != null){ for (String callback : components.getCallbacks().keySet()){ Callback resourceCallback = components.getCallbacks().get(callback); addCallbackSchemaRef(resourceCallback, referencedDefinitions); } } if (components.getPathItems() != null){ for (String resourcePath : components.getPathItems().keySet()){ PathItem pathItem = components.getPathItems().get(resourcePath); addPathItemSchemaRef(pathItem, referencedDefinitions); } } } protected OpenAPI removeBrokenReferenceDefinitions(OpenAPI openApi) { if (openApi == null || openApi.getComponents() == null || openApi.getComponents().getSchemas() == null) { return openApi; } Set referencedDefinitions = new TreeSet<>(); if (openApi.getPaths() != null) { for (String resourcePath : openApi.getPaths().keySet()) { PathItem pathItem = openApi.getPaths().get(resourcePath); addPathItemSchemaRef(pathItem, referencedDefinitions); } } if (openApi.getWebhooks() != null){ for (String resourcePath : openApi.getWebhooks().keySet()) { PathItem pathItem = openApi.getWebhooks().get(resourcePath); addPathItemSchemaRef(pathItem, referencedDefinitions); } } if (openApi.getComponents() != null){ Components components = openApi.getComponents(); addComponentsSchemaRef(components, referencedDefinitions); } referencedDefinitions.addAll(resolveAllNestedRefs(referencedDefinitions, referencedDefinitions, openApi)); openApi.getComponents() .getSchemas() .keySet() .retainAll(referencedDefinitions.stream() .map(s -> (String) RefUtils.extractSimpleName(s).getLeft()) .collect(Collectors.toSet())); return openApi; } protected Set resolveAllNestedRefs(Set refs, Set accumulatedRefs, OpenAPI openApi) { Set justDiscoveredReferencedDefinitions = new TreeSet<>(); for (String ref : refs) { locateReferencedDefinitions(ref, justDiscoveredReferencedDefinitions, openApi); } // Base case - no new references have been discovered. Halt discovery to avoid infinite loops if (accumulatedRefs.containsAll(justDiscoveredReferencedDefinitions)) { return Collections.emptySet(); } else { // Remove all refs that have already been discovered. justDiscoveredReferencedDefinitions.removeAll(accumulatedRefs); accumulatedRefs.addAll(justDiscoveredReferencedDefinitions); return resolveAllNestedRefs(justDiscoveredReferencedDefinitions, accumulatedRefs, openApi); } } protected void locateReferencedDefinitions(String ref, Set nestedReferencedDefinitions, OpenAPI openAPI) { nestedReferencedDefinitions.add(ref); String simpleName = (String) RefUtils.extractSimpleName(ref).getLeft(); Schema model = openAPI.getComponents().getSchemas().get(simpleName); if (model != null) { addSchemaRef(model, nestedReferencedDefinitions); } } private PathItem cloneFilteredPathItem(OpenAPISpecFilter filter, PathItem filteredPathItem, String resourcePath, Map> params, Map cookies, Map> headers, Set allowedTags, Set filteredTags) { if (filteredPathItem == null) { return null; } PathItem clonedPathItem = new PathItem(); clonedPathItem.set$ref(filteredPathItem.get$ref()); clonedPathItem.setDescription(filteredPathItem.getDescription()); clonedPathItem.setSummary(filteredPathItem.getSummary()); clonedPathItem.setExtensions(filteredPathItem.getExtensions()); clonedPathItem.setParameters(filteredPathItem.getParameters()); clonedPathItem.setServers(filteredPathItem.getServers()); Map ops = filteredPathItem.readOperationsMap(); for (Map.Entry entry : ops.entrySet()) { PathItem.HttpMethod key = entry.getKey(); Operation op = entry.getValue(); final List opTagsBeforeFilter; if (op.getTags() != null) { opTagsBeforeFilter = new ArrayList<>(op.getTags()); } else { opTagsBeforeFilter = new ArrayList<>(); } op = filterOperation(filter, op, resourcePath, key.toString(), params, cookies, headers); clonedPathItem.operation(key, op); if (op == null) { filteredTags.addAll(opTagsBeforeFilter); } else { if (op.getTags() != null) { opTagsBeforeFilter.removeAll(op.getTags()); allowedTags.addAll(op.getTags()); } filteredTags.addAll(opTagsBeforeFilter); } } return clonedPathItem; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/AbstractModelConverter.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyName; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.module.SimpleModule; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.util.ReflectionUtils; import io.swagger.v3.oas.models.media.Schema; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public abstract class AbstractModelConverter implements ModelConverter { protected final ObjectMapper _mapper; protected final TypeNameResolver _typeNameResolver; /** * Minor optimization: no need to keep on resolving same types over and over * again. */ protected Map _resolvedTypeNames = new ConcurrentHashMap<>(); protected AbstractModelConverter(ObjectMapper mapper) { this (mapper, TypeNameResolver.std); } protected AbstractModelConverter(ObjectMapper mapper, TypeNameResolver typeNameResolver) { mapper.registerModule( new SimpleModule("swagger", Version.unknownVersion()) { @Override public void setupModule(SetupContext context) { context.insertAnnotationIntrospector(new SwaggerAnnotationIntrospector()); } }); _mapper = mapper; _typeNameResolver = typeNameResolver; } @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { if (chain.hasNext()) { return chain.next().resolve(type, context, chain); } else { return null; } } /** * Retrieves the current AnnotationIntrospector from the ObjectMapper's serialization configuration. * We do not cache the value of _intr because users can load jackson modules later, * and we want to use their annotation inspection. * * @return the current AnnotationIntrospector */ protected AnnotationIntrospector _intr() { return _mapper.getSerializationConfig().getAnnotationIntrospector(); } protected String _typeName(JavaType type) { return _typeName(type, null); } protected String _typeName(JavaType type, BeanDescription beanDesc) { String name = _resolvedTypeNames.get(type); if (name != null) { return name; } name = _findTypeName(type, beanDesc); _resolvedTypeNames.put(type, name); return name; } protected String _findTypeName(JavaType type, BeanDescription beanDesc) { // First, handle container types; they require recursion if (type.isArrayType()) { return "Array"; } if (type.isMapLikeType() && ReflectionUtils.isSystemType(type)) { return "Map"; } if (type.isContainerType() && ReflectionUtils.isSystemType(type)) { if (Set.class.isAssignableFrom(type.getRawClass())) { return "Set"; } return "List"; } if (beanDesc == null) { beanDesc = _mapper.getSerializationConfig().introspectClassAnnotations(type); } PropertyName rootName = _intr().findRootName(beanDesc.getClassInfo()); if (rootName != null && rootName.hasSimpleName()) { return rootName.getSimpleName(); } return _typeNameResolver.nameForType(type); } protected String _typeQName(JavaType type) { return type.getRawClass().getName(); } protected String _subTypeName(NamedType type) { return type.getType().getName(); } protected boolean _isSetType(Class cls) { if (cls != null) { if (java.util.Set.class.equals(cls)) { return true; } else { for (Class a : cls.getInterfaces()) { // this is dirty and ugly and needs to be extended into a scala model converter. But to avoid bringing in scala runtime... if (java.util.Set.class.equals(a) || "interface scala.collection.Set".equals(a.toString())) { return true; } } } } return false; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ApiResponsesSerializer.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import io.swagger.v3.oas.models.responses.ApiResponses; import java.io.IOException; import java.util.Map; import java.util.Map.Entry; public class ApiResponsesSerializer extends JsonSerializer { @Override public void serialize( ApiResponses value, JsonGenerator jgen, SerializerProvider provider) throws IOException { if (value != null && value.getExtensions() != null && !value.getExtensions().isEmpty()) { jgen.writeStartObject(); if (!value.isEmpty()) { for (Entry entry: value.entrySet()) { jgen.writeObjectField(entry.getKey() , entry.getValue()); } } for (Map.Entry entry: value.getExtensions().entrySet()) { jgen.writeObjectField(entry.getKey(), entry.getValue()); } jgen.writeEndObject(); } else { provider.defaultSerializeValue(value, jgen); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/CallbackSerializer.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.callbacks.Callback; import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.util.Map.Entry; public class CallbackSerializer extends JsonSerializer { @Override public void serialize( Callback value, JsonGenerator jgen, SerializerProvider provider) throws IOException { // has extensions if (value != null && value.getExtensions() != null && !value.getExtensions().isEmpty()) { jgen.writeStartObject(); // not a ref if (StringUtils.isBlank(value.get$ref())) { if (!value.isEmpty()) { // write map for (Entry entry: value.entrySet()) { jgen.writeObjectField(entry.getKey() , entry.getValue()); } } } else { // handle ref schema serialization skipping all other props ... jgen.writeStringField("$ref", value.get$ref()); } for (String ext: value.getExtensions().keySet()) { jgen.writeObjectField(ext , value.getExtensions().get(ext)); } jgen.writeEndObject(); } else { if (value == null || StringUtils.isBlank(value.get$ref())) { provider.defaultSerializeValue(value, jgen); } else { // handle ref schema serialization skipping all other props jgen.writeStartObject(); jgen.writeStringField("$ref", value.get$ref()); jgen.writeEndObject(); } } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ExampleSerializer.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.ResolvableSerializer; import io.swagger.v3.oas.models.examples.Example; import java.io.IOException; public class ExampleSerializer extends JsonSerializer implements ResolvableSerializer { private JsonSerializer defaultSerializer; public ExampleSerializer(JsonSerializer serializer) { defaultSerializer = serializer; } @Override public void resolve(SerializerProvider serializerProvider) throws JsonMappingException { if (defaultSerializer instanceof ResolvableSerializer) { ((ResolvableSerializer) defaultSerializer).resolve(serializerProvider); } } @Override public void serialize( Example example, JsonGenerator jgen, SerializerProvider provider) throws IOException { if (example.getValueSetFlag() && example.getValue() == null) { jgen.writeStartObject(); defaultSerializer.unwrappingSerializer(null).serialize(example, jgen, provider); jgen.writeNullField("value"); jgen.writeEndObject(); } else { defaultSerializer.serialize(example, jgen, provider); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/JAXBAnnotationsHelper.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.databind.introspect.Annotated; import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.MapSchema; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.XML; import org.apache.commons.lang3.StringUtils; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import java.lang.annotation.Annotation; /** * The JAXBAnnotationsHelper class defines helper methods for * applying JAXB annotations to property definitions. */ class JAXBAnnotationsHelper { public static final String JAXB_DEFAULT = "##default"; private JAXBAnnotationsHelper() { } /** * Applies annotations to property's {@link XML} definition. * * @param member annotations provider * @param property property instance to be updated */ public static void apply(Annotated member, Annotation[] annotations, Schema property) { XmlElementWrapper wrapper = member.getAnnotation(XmlElementWrapper.class); if (wrapper == null) { wrapper = AnnotationsUtils.getAnnotation(XmlElementWrapper.class, annotations); } XmlAttribute attr = member.getAnnotation(XmlAttribute.class); if (attr == null) { attr = AnnotationsUtils.getAnnotation(XmlAttribute.class, annotations); } XmlElement elem = member.getAnnotation(XmlElement.class); if (elem == null) { elem = AnnotationsUtils.getAnnotation(XmlElement.class, annotations); } if (wrapper != null) { applyElement(wrapper, property); } else if (elem != null) { applyElement(elem, property); } else if (attr != null && isAttributeAllowed(property)) { applyAttribute(attr, property); } } /** * Puts definitions for XML wrapper. * * @param wrapper XmlElementWrapper * @param property property instance to be updated */ private static void applyElement(XmlElementWrapper wrapper, Schema property) { if (wrapper != null) { final XML xml = getXml(property); xml.setWrapped(true); // No need to set the xml name if the name provided by xmlelementwrapper annotation is ##default or equal to the property name | https://github.com/swagger-api/swagger-core/pull/2050 if (!JAXB_DEFAULT.equals(wrapper.name()) && !wrapper.name().isEmpty() && !wrapper.name().equals(property.getName())) { xml.setName(wrapper.name()); } } } /** * Puts definitions for XML element. * * @param element XmlElement * @param property property instance to be updated */ private static void applyElement(XmlElement element, Schema property) { if (element != null) { setName(element.namespace(), element.name(), property); } } /** * Puts definitions for XML attribute. * * @param attribute XmlAttribute * @param property property instance to be updated */ private static void applyAttribute(XmlAttribute attribute, Schema property) { if (attribute != null) { final XML xml = getXml(property); xml.setAttribute(true); setName(attribute.namespace(), attribute.name(), property); } } private static XML getXml(Schema property) { final XML existing = property.getXml(); if (existing != null) { return existing; } final XML created = new XML(); property.setXml(created); return created; } /** * Puts name space and name for XML node or attribute. * * @param ns name space * @param name name * @param property property instance to be updated * @return true if name space and name have been set */ private static boolean setName(String ns, String name, Schema property) { boolean apply = false; final String cleanName = StringUtils.trimToNull(name); final String useName; if (!isEmpty(cleanName) && !cleanName.equals(property.getName())) { useName = cleanName; apply = true; } else { useName = null; } final String cleanNS = StringUtils.trimToNull(ns); final String useNS; if (!isEmpty(cleanNS)) { useNS = cleanNS; apply = true; } else { useNS = null; } // Set everything or nothing if (apply) { getXml(property).name(useName).namespace(useNS); } return apply; } /** * Checks whether the passed property can be represented as node attribute. * * @param property property instance to be checked * @return true if the passed property can be represented as * node attribute */ private static boolean isAttributeAllowed(Schema property) { for (Class item : new Class[]{ArraySchema.class, MapSchema.class, ObjectSchema.class}) { if (item.isInstance(property)) { return false; } } return StringUtils.isBlank(property.get$ref()); } private static boolean isEmpty(String name) { return StringUtils.isEmpty(name) || JAXB_DEFAULT.equals(name); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/MediaTypeSerializer.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.ResolvableSerializer; import io.swagger.v3.oas.models.media.MediaType; import java.io.IOException; public class MediaTypeSerializer extends JsonSerializer implements ResolvableSerializer { private JsonSerializer defaultSerializer; public MediaTypeSerializer(JsonSerializer serializer) { defaultSerializer = serializer; } @Override public void resolve(SerializerProvider serializerProvider) throws JsonMappingException { if (defaultSerializer instanceof ResolvableSerializer) { ((ResolvableSerializer) defaultSerializer).resolve(serializerProvider); } } @Override public void serialize( MediaType value, JsonGenerator jgen, SerializerProvider provider) throws IOException { if (value.getExampleSetFlag() && value.getExample() == null) { jgen.writeStartObject(); defaultSerializer.unwrappingSerializer(null).serialize(value, jgen, provider); jgen.writeNullField("example"); jgen.writeEndObject(); } else { defaultSerializer.serialize(value, jgen, provider); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyMetadata; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.AnnotatedField; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder; import com.fasterxml.jackson.databind.jsontype.NamedType; import com.fasterxml.jackson.databind.util.Annotations; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.util.*; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.media.DependentRequired; import io.swagger.v3.oas.annotations.media.DependentSchema; import io.swagger.v3.oas.annotations.media.DependentSchemas; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; import io.swagger.v3.oas.annotations.media.PatternProperties; import io.swagger.v3.oas.annotations.media.PatternProperty; import io.swagger.v3.oas.annotations.media.SchemaProperties; import io.swagger.v3.oas.annotations.media.SchemaProperty; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.ExternalDocumentation; import io.swagger.v3.oas.models.SpecVersion; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.Discriminator; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.JsonSchema; import io.swagger.v3.oas.models.media.MapSchema; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.media.UUIDSchema; import io.swagger.v3.oas.models.media.XML; import javax.validation.constraints.Email; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlElementRefs; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSchema; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedParameterizedType; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; import static io.swagger.v3.core.jackson.JAXBAnnotationsHelper.JAXB_DEFAULT; import static io.swagger.v3.core.util.RefUtils.constructRef; import static io.swagger.v3.core.util.SiblingAnnotationFilter.filterSiblingAnnotations; import static io.swagger.v3.core.util.ValidationAnnotationsUtils.*; import static io.swagger.v3.oas.annotations.media.Schema.DEFAULT_SENTINEL; public class ModelResolver extends AbstractModelConverter implements ModelConverter { Logger LOGGER = LoggerFactory.getLogger(ModelResolver.class); public static List NOT_NULL_ANNOTATIONS = Arrays.asList("NotNull", "NonNull", "NotBlank", "NotEmpty"); public static List NULLABLE_ANNOTATIONS = Arrays.asList("Nullable"); public static final String SET_PROPERTY_OF_COMPOSED_MODEL_AS_SIBLING = "composed-model-properties-as-sibiling"; public static final String SET_PROPERTY_OF_ENUMS_AS_REF = "enums-as-ref"; public static boolean composedModelPropertiesAsSibling = System.getProperty(SET_PROPERTY_OF_COMPOSED_MODEL_AS_SIBLING) != null; private static final int SCHEMA_COMPONENT_PREFIX = "#/components/schemas/".length(); /** * Allows all enums to be resolved as a reference to a scheme added to the components section. */ public static boolean enumsAsRef = System.getProperty(SET_PROPERTY_OF_ENUMS_AS_REF) != null; private boolean openapi31; private Schema.SchemaResolution schemaResolution = Schema.SchemaResolution.DEFAULT; protected Configuration configuration = new Configuration(); protected ValidatorProcessor validatorProcessor; protected Set typesBeingResolved = new HashSet<>(); public ModelResolver(ObjectMapper mapper) { super(mapper); } public ModelResolver(ObjectMapper mapper, TypeNameResolver typeNameResolver) { super(mapper, typeNameResolver); } public ObjectMapper objectMapper() { return _mapper; } @Override public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context, Iterator next) { boolean implicitObject = false; boolean isPrimitive = false; Schema model = null; List requiredProps = new ArrayList<>(); if (annotatedType == null) { return null; } if (this.shouldIgnoreClass(annotatedType.getType())) { return null; } final JavaType type; if (annotatedType.getType() instanceof JavaType) { type = (JavaType) annotatedType.getType(); } else { type = _mapper.constructType(annotatedType.getType()); } final Annotation resolvedSchemaOrArrayAnnotation = AnnotationsUtils.mergeSchemaAnnotations(annotatedType.getCtxAnnotations(), type); final io.swagger.v3.oas.annotations.media.Schema resolvedSchemaAnnotation = resolvedSchemaOrArrayAnnotation == null ? null : resolvedSchemaOrArrayAnnotation instanceof io.swagger.v3.oas.annotations.media.ArraySchema ? ((io.swagger.v3.oas.annotations.media.ArraySchema) resolvedSchemaOrArrayAnnotation).schema() : (io.swagger.v3.oas.annotations.media.Schema) resolvedSchemaOrArrayAnnotation; final io.swagger.v3.oas.annotations.media.ArraySchema resolvedArrayAnnotation = resolvedSchemaOrArrayAnnotation == null ? null : resolvedSchemaOrArrayAnnotation instanceof io.swagger.v3.oas.annotations.media.ArraySchema ? (io.swagger.v3.oas.annotations.media.ArraySchema) resolvedSchemaOrArrayAnnotation : null; final BeanDescription beanDesc; { BeanDescription recurBeanDesc = _mapper.getSerializationConfig().introspect(type); HashSet visited = new HashSet<>(); JsonSerialize jsonSerialize = recurBeanDesc.getClassAnnotations().get(JsonSerialize.class); while (jsonSerialize != null && !Void.class.equals(jsonSerialize.as())) { String asName = jsonSerialize.as().getName(); if (visited.contains(asName)) break; visited.add(asName); recurBeanDesc = _mapper.getSerializationConfig().introspect( _mapper.constructType(jsonSerialize.as()) ); jsonSerialize = recurBeanDesc.getClassAnnotations().get(JsonSerialize.class); } beanDesc = recurBeanDesc; } String name = annotatedType.getName(); if (StringUtils.isBlank(name)) { // allow override of name from annotation if (!annotatedType.isSkipSchemaName() && resolvedSchemaAnnotation != null && !resolvedSchemaAnnotation.name().isEmpty()) { name = resolvedSchemaAnnotation.name(); } if (StringUtils.isBlank(name) && (type.isEnumType() || !ReflectionUtils.isSystemType(type))) { name = _typeName(type, beanDesc); } } name = decorateModelName(annotatedType, name); // if we have a ref, for OAS 3.0 we don't consider anything else, while for OAS 3.1 we store the ref and add it later String schemaRefFromAnnotation = null; if (resolvedSchemaAnnotation != null && StringUtils.isNotEmpty(resolvedSchemaAnnotation.ref())) { if (resolvedArrayAnnotation == null) { schemaRefFromAnnotation = resolvedSchemaAnnotation.ref(); if (!openapi31) { return new Schema().$ref(resolvedSchemaAnnotation.ref()).name(name); } } else { ArraySchema schema = new ArraySchema(); if (openapi31) { schema.specVersion(SpecVersion.V31); } resolveArraySchema(annotatedType, schema, resolvedArrayAnnotation); Schema itemsSchema = openapi31 ? new JsonSchema() : new Schema(); return schema.items(itemsSchema.$ref(resolvedSchemaAnnotation.ref()).name(name)); } } if (!annotatedType.isSkipOverride() && resolvedSchemaAnnotation != null && !Void.class.equals(resolvedSchemaAnnotation.implementation())) { Class cls = resolvedSchemaAnnotation.implementation(); LOGGER.debug("overriding datatype from {} to {}", type, cls.getName()); Annotation[] ctxAnnotation = null; if (resolvedArrayAnnotation != null && annotatedType.getCtxAnnotations() != null) { List annList = new ArrayList<>(); for (Annotation a: annotatedType.getCtxAnnotations()) { if (!(a instanceof ArraySchema)) { annList.add(a); } } annList.add(resolvedSchemaAnnotation); ctxAnnotation = annList.toArray(new Annotation[annList.size()]); } else { ctxAnnotation = annotatedType.getCtxAnnotations(); } AnnotatedType aType = new AnnotatedType() .type(cls) .ctxAnnotations(ctxAnnotation) .parent(annotatedType.getParent()) .name(annotatedType.getName()) .resolveAsRef(annotatedType.isResolveAsRef()) .jsonViewAnnotation(annotatedType.getJsonViewAnnotation()) .propertyName(annotatedType.getPropertyName()) .components(annotatedType.getComponents()) .skipOverride(true); if (resolvedArrayAnnotation != null) { ArraySchema schema = new ArraySchema(); if (openapi31) { schema.specVersion(SpecVersion.V31); } resolveArraySchema(annotatedType, schema, resolvedArrayAnnotation); Schema innerSchema = null; Schema primitive = PrimitiveType.createProperty(cls, openapi31); if (primitive != null) { innerSchema = primitive; } else { innerSchema = context.resolve(aType); if (innerSchema != null && isObjectSchema(innerSchema) && StringUtils.isNotBlank(innerSchema.getName())) { // create a reference for the items if (context.getDefinedModels().containsKey(innerSchema.getName())) { String ref = constructRef(innerSchema.getName()); innerSchema = openapi31 ? new JsonSchema() : new Schema(); innerSchema.$ref(ref); } } else if (innerSchema != null && innerSchema.get$ref() != null) { String ref = StringUtils.isNotEmpty(innerSchema.get$ref()) ? innerSchema.get$ref() : innerSchema.getName(); innerSchema = openapi31 ? new JsonSchema() : new Schema(); innerSchema.$ref(ref); } } schema.setItems(innerSchema); return schema; } else { Schema implSchema = context.resolve(aType); if (implSchema != null && aType.isResolveAsRef() && isObjectSchema(implSchema) && StringUtils.isNotBlank(implSchema.getName())) { // create a reference for the items if (context.getDefinedModels().containsKey(implSchema.getName())) { String ref = constructRef(implSchema.getName()); implSchema = openapi31 ? new JsonSchema() : new Schema(); implSchema.$ref(ref); } } else if (implSchema != null && implSchema.get$ref() != null) { String ref = StringUtils.isNotEmpty(implSchema.get$ref()) ? implSchema.get$ref() : implSchema.getName(); implSchema = openapi31 ? new JsonSchema() : new Schema(); implSchema.$ref(ref); } return implSchema; } } if (model == null && !annotatedType.isSkipOverride() && resolvedSchemaAnnotation != null && StringUtils.isNotEmpty(resolvedSchemaAnnotation.type()) && !resolvedSchemaAnnotation.type().equals("object")) { PrimitiveType primitiveType = PrimitiveType.fromTypeAndFormat(resolvedSchemaAnnotation.type(), resolvedSchemaAnnotation.format()); if (primitiveType == null) { primitiveType = PrimitiveType.fromType(type); } if (primitiveType == null) { primitiveType = PrimitiveType.fromName(resolvedSchemaAnnotation.type()); } if (primitiveType != null) { Schema primitive = openapi31 ? primitiveType.createProperty31() : primitiveType.createProperty(); model = primitive; isPrimitive = true; } } if (model == null && type.isEnumType()) { @SuppressWarnings("unchecked") Class> rawEnumClass = (Class>) type.getRawClass(); model = _createSchemaForEnum(rawEnumClass); isPrimitive = true; } if (model == null) { if (resolvedSchemaAnnotation != null && StringUtils.isEmpty(resolvedSchemaAnnotation.type())) { PrimitiveType primitiveType = PrimitiveType.fromTypeAndFormat(type, resolvedSchemaAnnotation.format()); if (primitiveType != null) { model = openapi31 ? primitiveType.createProperty31() : primitiveType.createProperty(); isPrimitive = true; } } if (model == null) { PrimitiveType primitiveType = PrimitiveType.fromType(type); if (primitiveType != null) { model = openapi31 ? primitiveType.createProperty31() : primitiveType.createProperty(); isPrimitive = true; } } } if (!annotatedType.isSkipJsonIdentity()) { JsonIdentityInfo jsonIdentityInfo = AnnotationsUtils.getAnnotation(JsonIdentityInfo.class, annotatedType.getCtxAnnotations()); if (jsonIdentityInfo == null) { jsonIdentityInfo = type.getRawClass().getAnnotation(JsonIdentityInfo.class); } if (model == null && jsonIdentityInfo != null) { JsonIdentityReference jsonIdentityReference = AnnotationsUtils.getAnnotation(JsonIdentityReference.class, annotatedType.getCtxAnnotations()); if (jsonIdentityReference == null) { jsonIdentityReference = type.getRawClass().getAnnotation(JsonIdentityReference.class); } model = new GeneratorWrapper().processJsonIdentity(annotatedType, context, _mapper, jsonIdentityInfo, jsonIdentityReference); if (model != null) { return model; } } } if (model == null && annotatedType.getJsonUnwrappedHandler() != null) { model = annotatedType.getJsonUnwrappedHandler().apply(annotatedType); if (model == null) { return null; } } if ("Object".equals(name)) { Schema schema = openapi31 ? new JsonSchema() : new Schema(); if (schemaRefFromAnnotation != null) { schema.raw$ref(schemaRefFromAnnotation); } return schema; } List> composedSchemaReferencedClasses = getComposedSchemaReferencedClasses(type.getRawClass(), annotatedType.getCtxAnnotations(), resolvedSchemaAnnotation); boolean hasCompositionKeywords = composedSchemaReferencedClasses != null; if (isPrimitive) { XML xml = resolveXml(beanDesc.getClassInfo(), annotatedType.getCtxAnnotations(), resolvedSchemaAnnotation); if (xml != null) { model.xml(xml); } if (!type.isEnumType()){ applyBeanValidatorAnnotations(model, annotatedType.getCtxAnnotations(), null, false); } resolveSchemaMembers(model, annotatedType, context, next); if (resolvedArrayAnnotation != null) { ArraySchema schema = new ArraySchema(); if (openapi31) { schema.specVersion(SpecVersion.V31); } resolveArraySchema(annotatedType, schema, resolvedArrayAnnotation); schema.setItems(model); return schema; } if (type.isEnumType() && shouldResolveEnumAsRef(resolvedSchemaAnnotation, annotatedType.isResolveEnumAsRef())) { // Store off the ref and add the enum as a top-level model context.defineModel(name, model, annotatedType, null); // Return the model as a ref only property model = openapi31 ? new JsonSchema() : new Schema(); model.$ref(Components.COMPONENTS_SCHEMAS_REF + name); } if (!hasCompositionKeywords) { if (schemaRefFromAnnotation != null && model != null) { model.raw$ref(schemaRefFromAnnotation); } return model; } } /** * --Preventing parent/child hierarchy creation loops - Comment 1-- * Creating a parent model will result in the creation of child models. Creating a child model will result in * the creation of a parent model, as per the second If statement following this comment. * * By checking whether a model has already been resolved (as implemented below), loops of parents creating * children and children creating parents can be short-circuited. This works because currently the * ModelConverterContextImpl will return null for a class that already been processed, but has not yet been * defined. This logic works in conjunction with the early immediate definition of model in the context * implemented later in this method (See "Preventing parent/child hierarchy creation loops - Comment 2") to * prevent such */ Schema resolvedModel = context.resolve(annotatedType); if (resolvedModel != null) { if (name != null && name.equals(resolvedModel.getName())) { return resolvedModel; } } Type jsonValueType = findJsonValueType(beanDesc); if(jsonValueType != null) { AnnotatedType aType = new AnnotatedType() .type(jsonValueType) .parent(annotatedType.getParent()) .name(annotatedType.getName()) .schemaProperty(annotatedType.isSchemaProperty()) .resolveAsRef(annotatedType.isResolveAsRef()) .jsonViewAnnotation(annotatedType.getJsonViewAnnotation()) .propertyName(annotatedType.getPropertyName()) .ctxAnnotations(annotatedType.getCtxAnnotations()) .components(annotatedType.getComponents()) .skipOverride(true); return context.resolve(aType); } boolean isStreamWithArrayAnnotation = resolvedArrayAnnotation != null && isStreamType(type); if (type.isContainerType()) { // TODO currently a MapSchema or ArraySchema don't also support composed schema props (oneOf,..) hasCompositionKeywords = false; JavaType keyType = type.getKeyType(); JavaType valueType = type.getContentType(); String pName = null; if (valueType != null) { BeanDescription valueTypeBeanDesc = _mapper.getSerializationConfig().introspect(valueType); pName = _typeName(valueType, valueTypeBeanDesc); } List strippedCtxAnnotations = new ArrayList<>(); if (resolvedSchemaAnnotation != null) { strippedCtxAnnotations.add(0, resolvedSchemaAnnotation); } if (annotatedType.getCtxAnnotations() != null) { strippedCtxAnnotations.addAll(Arrays.stream( annotatedType.getCtxAnnotations()).filter( ass -> !ass.annotationType().getName().startsWith("io.swagger") && !ass.annotationType().getName().startsWith("javax.validation.constraints") ).collect(Collectors.toList())); } Schema.SchemaResolution containerResolvedSchemaResolution = AnnotationsUtils.resolveSchemaResolution(this.schemaResolution, resolvedSchemaAnnotation); if (keyType != null && valueType != null) { if (ReflectionUtils.isSystemTypeNotArray(type) && !annotatedType.isSchemaProperty() && !annotatedType.isResolveAsRef()) { context.resolve(new AnnotatedType().components(annotatedType.getComponents()).type(valueType).jsonViewAnnotation(annotatedType.getJsonViewAnnotation())); return null; } Schema addPropertiesSchema = context.resolve( new AnnotatedType() .type(valueType) .schemaProperty(annotatedType.isSchemaProperty()) .ctxAnnotations(strippedCtxAnnotations.toArray(new Annotation[0])) .skipSchemaName(true) .resolveAsRef(annotatedType.isResolveAsRef()) .jsonViewAnnotation(annotatedType.getJsonViewAnnotation()) .propertyName(annotatedType.getPropertyName()) .components(annotatedType.getComponents()) .parent(annotatedType.getParent())); if (addPropertiesSchema != null) { if (StringUtils.isNotBlank(addPropertiesSchema.getName())) { pName = addPropertiesSchema.getName(); } if (isObjectSchema(addPropertiesSchema) && pName != null) { if (context.getDefinedModels().containsKey(pName)) { if (Schema.SchemaResolution.INLINE.equals(containerResolvedSchemaResolution) && applySchemaResolution()) { addPropertiesSchema = context.getDefinedModels().get(pName); } else { // create a reference for the items addPropertiesSchema = openapi31 ? new JsonSchema() : new Schema(); addPropertiesSchema.$ref(constructRef(pName)); } } } else if (addPropertiesSchema.get$ref() != null) { String ref = StringUtils.isNotEmpty(addPropertiesSchema.get$ref()) ? addPropertiesSchema.get$ref() : addPropertiesSchema.getName(); addPropertiesSchema = openapi31 ? new JsonSchema() : new Schema(); addPropertiesSchema.$ref(ref); } } Schema mapModel = new MapSchema().additionalProperties(addPropertiesSchema); if (openapi31) { mapModel.specVersion(SpecVersion.V31); } mapModel.name(name); model = mapModel; } else if (valueType != null) { if (!isStreamWithArrayAnnotation && ReflectionUtils.isSystemTypeNotArray(type) && !annotatedType.isSchemaProperty() && !annotatedType.isResolveAsRef()) { context.resolve(new AnnotatedType().components(annotatedType.getComponents()).type(valueType).jsonViewAnnotation(annotatedType.getJsonViewAnnotation())); return null; } Schema items = context.resolve(new AnnotatedType() .type(valueType) .schemaProperty(annotatedType.isSchemaProperty()) .ctxAnnotations(strippedCtxAnnotations.toArray(new Annotation[0])) .skipSchemaName(true) .resolveAsRef(annotatedType.isResolveAsRef()) .propertyName(annotatedType.getPropertyName()) .jsonViewAnnotation(annotatedType.getJsonViewAnnotation()) .components(annotatedType.getComponents()) .resolveEnumAsRef(annotatedType.isResolveEnumAsRef()) .parent(annotatedType.getParent())); if (items == null) { return null; } if (annotatedType.isSchemaProperty() && annotatedType.getCtxAnnotations() != null && annotatedType.getCtxAnnotations().length > 0) { if (!"object".equals(items.getType())) { for (Annotation annotation : annotatedType.getCtxAnnotations()) { if (annotation instanceof XmlElement) { XmlElement xmlElement = (XmlElement) annotation; if (xmlElement != null && xmlElement.name() != null && !"".equals(xmlElement.name()) && !JAXB_DEFAULT.equals(xmlElement.name())) { XML xml = items.getXml() != null ? items.getXml() : new XML(); xml.setName(xmlElement.name()); items.setXml(xml); } } } } } if (StringUtils.isNotBlank(items.getName())) { pName = items.getName(); } if (isObjectSchema(items) && pName != null) { if (context.getDefinedModels().containsKey(pName)) { if (Schema.SchemaResolution.INLINE.equals(containerResolvedSchemaResolution) && applySchemaResolution()) { items = context.getDefinedModels().get(pName); } else { // create a reference for the items items = openapi31 ? new JsonSchema() : new Schema(); items.$ref(constructRef(pName)); } } } else if (items.get$ref() != null) { String ref = StringUtils.isNotEmpty(items.get$ref()) ? items.get$ref() : items.getName(); items = openapi31 ? new JsonSchema() : new Schema(); items.$ref(ref); } Schema arrayModel = new ArraySchema().items(items); if (openapi31) { arrayModel.specVersion(SpecVersion.V31); } if (_isSetType(type.getRawClass())) { arrayModel.setUniqueItems(true); } arrayModel.name(name); model = arrayModel; } else { if (ReflectionUtils.isSystemType(type) && !annotatedType.isSchemaProperty() && !annotatedType.isResolveAsRef()) { return null; } } } else if (hasCompositionKeywords) { model = openapi31 ? new JsonSchema() : new ComposedSchema(); model.name(name); if ( (openapi31 && Boolean.TRUE.equals(PrimitiveType.explicitObjectType)) || (!openapi31 && (!Boolean.FALSE.equals(PrimitiveType.explicitObjectType)))) { if (openapi31 && resolvedArrayAnnotation == null) { model.addType("object"); } else { model.type("object"); } } else { implicitObject = true; } } else { AnnotatedType aType = ReferenceTypeUtils.unwrapReference(annotatedType); if (aType != null) { model = context.resolve(aType); return model; } else { model = openapi31 ? new JsonSchema().name(name) : new Schema().name(name); if ((openapi31 && Boolean.TRUE.equals(PrimitiveType.explicitObjectType)) || (!openapi31 && (!Boolean.FALSE.equals(PrimitiveType.explicitObjectType)))) { if (openapi31 && resolvedArrayAnnotation == null) { model.addType("object"); } else { model.type("object"); } } else { implicitObject = true; } } } if (!type.isContainerType() && StringUtils.isNotBlank(name)) { // define the model here to support self/cyclic referencing of models context.defineModel(name, model, annotatedType, null); } XML xml = resolveXml(beanDesc.getClassInfo(), annotatedType.getCtxAnnotations(), resolvedSchemaAnnotation); if (xml != null) { model.xml(xml); } if (!(model instanceof ArraySchema) || (model instanceof ArraySchema && resolvedArrayAnnotation == null)) { resolveSchemaMembers(model, annotatedType, context, next); } final XmlAccessorType xmlAccessorTypeAnnotation = beanDesc.getClassAnnotations().get(XmlAccessorType.class); // see if @JsonIgnoreProperties exist Set propertiesToIgnore = resolveIgnoredProperties(beanDesc.getClassAnnotations(), annotatedType.getCtxAnnotations()); List props = new ArrayList<>(); Map modelProps = new LinkedHashMap<>(); List properties = beanDesc.findProperties(); List ignoredProps = getIgnoredProperties(beanDesc); properties.removeIf(p -> ignoredProps.contains(p.getName())); for (BeanPropertyDefinition propDef : properties) { Schema property = null; String propName = propDef.getName(); Annotation[] annotations = null; AnnotatedMember member = propDef.getPrimaryMember(); if (member == null) { final BeanDescription deserBeanDesc = _mapper.getDeserializationConfig().introspect(type); List deserProperties = deserBeanDesc.findProperties(); for (BeanPropertyDefinition prop : deserProperties) { if (StringUtils.isNotBlank(prop.getInternalName()) && prop.getInternalName().equals(propDef.getInternalName())) { member = prop.getPrimaryMember(); break; } } } // hack to avoid clobbering properties with get/is names // it's ugly but gets around https://github.com/swagger-api/swagger-core/issues/415 if (propDef.getPrimaryMember() != null) { final JsonProperty jsonPropertyAnn = propDef.getPrimaryMember().getAnnotation(JsonProperty.class); if (jsonPropertyAnn == null || !jsonPropertyAnn.value().equals(propName)) { if (member != null) { java.lang.reflect.Member innerMember = member.getMember(); if (innerMember != null) { String altName = innerMember.getName(); if (altName != null) { final int length = altName.length(); for (String prefix : Arrays.asList("get", "is")) { final int offset = prefix.length(); if (altName.startsWith(prefix) && length > offset && !Character.isUpperCase(altName.charAt(offset))) { propName = altName; break; } } } } } } } PropertyMetadata md = propDef.getMetadata(); if (member != null && !ignore(member, xmlAccessorTypeAnnotation, propName, propertiesToIgnore, propDef)) { List annotationList = new ArrayList<>(); for (Annotation a : member.annotations()) { annotationList.add(a); } annotations = annotationList.toArray(new Annotation[annotationList.size()]); if (hiddenByJsonView(annotations, annotatedType)) { continue; } JavaType propType = member.getType(); if (propType != null && "void".equals(propType.getRawClass().getName())) { if (member instanceof AnnotatedMethod) { propType = ((AnnotatedMethod) member).getParameterType(0); } } String propSchemaName = null; io.swagger.v3.oas.annotations.media.Schema ctxSchema = AnnotationsUtils.getSchemaAnnotation(annotations); if (AnnotationsUtils.hasSchemaAnnotation(ctxSchema)) { if (!StringUtils.isBlank(ctxSchema.name())) { propSchemaName = ctxSchema.name(); } } io.swagger.v3.oas.annotations.media.ArraySchema ctxArraySchema = AnnotationsUtils.getArraySchemaAnnotation(annotations); if (propSchemaName == null) { if (AnnotationsUtils.hasArrayAnnotation(ctxArraySchema)) { if (AnnotationsUtils.hasSchemaAnnotation(ctxArraySchema.schema())) { if (!StringUtils.isBlank(ctxArraySchema.schema().name())) { propSchemaName = ctxArraySchema.schema().name(); } } } } if (StringUtils.isNotBlank(propSchemaName)) { propName = propSchemaName; } Annotation propSchemaOrArray = AnnotationsUtils.mergeSchemaAnnotations(annotations, propType); final io.swagger.v3.oas.annotations.media.Schema propResolvedSchemaAnnotation = propSchemaOrArray == null ? null : propSchemaOrArray instanceof io.swagger.v3.oas.annotations.media.ArraySchema ? ((io.swagger.v3.oas.annotations.media.ArraySchema) propSchemaOrArray).arraySchema() : (io.swagger.v3.oas.annotations.media.Schema) propSchemaOrArray; io.swagger.v3.oas.annotations.media.Schema.AccessMode accessMode = resolveAccessMode(propDef, type, propResolvedSchemaAnnotation); io.swagger.v3.oas.annotations.media.Schema.RequiredMode requiredMode = resolveRequiredMode(propResolvedSchemaAnnotation, propType); SiblingAnnotationFilter.FilterResult filterResult = filterSiblingAnnotations( annotations, propType, ctxSchema, ctxArraySchema, this.schemaResolution, openapi31); Annotation[] ctxFilteredSiblingAnnotations = filterResult.getFilteredAnnotations(); Schema.SchemaResolution resolvedSchemaResolution = filterResult.getResolvedSchemaResolution(); Set validationInvocationAnnotations = null; if (validatorProcessor != null) { validationInvocationAnnotations = validatorProcessor.resolveInvocationAnnotations(annotations); if (validationInvocationAnnotations == null) { validationInvocationAnnotations = validatorProcessor.resolveInvocationAnnotations(annotatedType.getCtxAnnotations()); } else { validationInvocationAnnotations.addAll(validatorProcessor.resolveInvocationAnnotations(annotatedType.getCtxAnnotations())); } } if (validationInvocationAnnotations == null) { validationInvocationAnnotations = resolveValidationInvocationAnnotations(annotations); validationInvocationAnnotations.addAll(resolveValidationInvocationAnnotations(annotatedType.getCtxAnnotations())); } annotations = Stream.concat(Arrays.stream(annotations), Arrays.stream(validationInvocationAnnotations.toArray(new Annotation[0]))).toArray(Annotation[]::new); if (ctxFilteredSiblingAnnotations != null) { ctxFilteredSiblingAnnotations = Stream.concat(Arrays.stream(ctxFilteredSiblingAnnotations), Arrays.stream(validationInvocationAnnotations.toArray(new Annotation[0]))).toArray(Annotation[]::new); } AnnotatedType aType = new AnnotatedType() .type(propType) .parent(model) .resolveAsRef(annotatedType.isResolveAsRef()) .jsonViewAnnotation(annotatedType.getJsonViewAnnotation()) .skipSchemaName(true) .subtype(annotatedType.isSubtype()) .schemaProperty(true) .components(annotatedType.getComponents()) .propertyName(propName) .resolveEnumAsRef(AnnotationsUtils.computeEnumAsRef(ctxSchema, ctxArraySchema)); if (AnnotationsUtils.areSiblingsAllowed(resolvedSchemaResolution, openapi31)) { aType.ctxAnnotations(ctxFilteredSiblingAnnotations); } else { aType.ctxAnnotations(annotations); } final AnnotatedMember propMember = member; aType.jsonUnwrappedHandler(t -> { JsonUnwrapped uw = propMember.getAnnotation(JsonUnwrapped.class); if (uw != null && uw.enabled()) { t .ctxAnnotations(null) .jsonUnwrappedHandler(null) .resolveAsRef(false); Schema innerModel = context.resolve(t); if (StringUtils.isNotBlank(innerModel.get$ref())) { innerModel = context.getDefinedModels().get(innerModel.get$ref().substring(SCHEMA_COMPONENT_PREFIX)); } handleUnwrapped(props, innerModel, uw.prefix(), uw.suffix(), requiredProps); return null; } else { return openapi31 ? new JsonSchema() : new Schema(); } }); boolean areSiblingsAllowed = AnnotationsUtils.areSiblingsAllowed(resolvedSchemaResolution, openapi31); aType = AnnotationsUtils.addTypeWhenSiblingsAllowed(aType, ctxSchema, areSiblingsAllowed); property = context.resolve(aType); property = clone(property); Schema ctxProperty = null; if (!applySchemaResolution()) { Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, property, schemaResolution, context); if (reResolvedProperty.isPresent()) { property = reResolvedProperty.get(); } reResolvedProperty = resolveArraySchemaWithCycleGuard(ctxArraySchema, annotatedType, openapi31, property); if (reResolvedProperty.isPresent()) { property = reResolvedProperty.get(); } } else if (Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution)) { Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, null, schemaResolution, context); if (reResolvedProperty.isPresent()) { ctxProperty = reResolvedProperty.get(); } reResolvedProperty = AnnotationsUtils.getArraySchema(ctxArraySchema, annotatedType.getComponents(), null, openapi31, ctxProperty); if (reResolvedProperty.isPresent()) { ctxProperty = reResolvedProperty.get(); } } if (property != null) { Boolean required = md.getRequired(); if (!io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED.equals(requiredMode)) { if (required != null && !Boolean.FALSE.equals(required)) { addRequiredItem(model, propName); } else { if (propDef.isRequired()) { addRequiredItem(model, propName); } } } if (property.get$ref() == null || openapi31) { if (accessMode != null) { switch (accessMode) { case AUTO: break; case READ_ONLY: property.readOnly(true); break; case READ_WRITE: break; case WRITE_ONLY: property.writeOnly(true); break; default: } } } final BeanDescription propBeanDesc = _mapper.getSerializationConfig().introspect(propType); if (property != null && !propType.isContainerType()) { if (isObjectSchema(property)) { // create a reference for the property String pName = _typeName(propType, propBeanDesc); if (StringUtils.isNotBlank(property.getName())) { pName = property.getName(); } if (context.getDefinedModels().containsKey(pName)) { if (Schema.SchemaResolution.INLINE.equals(resolvedSchemaResolution)) { property = context.getDefinedModels().get(pName); } else if (Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) && ctxProperty != null) { property = openapi31 ? new JsonSchema() : new Schema(); property .addAllOfItem(ctxProperty) .addAllOfItem(openapi31 ? new JsonSchema().$ref(constructRef(pName)) : new Schema().$ref(constructRef(pName))); } else if (Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution) && ctxProperty != null) { property = ctxProperty.addAllOfItem(openapi31 ? new JsonSchema().$ref(constructRef(pName)) : new Schema().$ref(constructRef(pName))); } else { property = openapi31 ? new JsonSchema() : new Schema(); property.$ref(constructRef(pName)); } property = clone(property); // TODO: why is this needed? is it not handled before? if (openapi31 || Schema.SchemaResolution.INLINE.equals(resolvedSchemaResolution)) { Optional reResolvedProperty = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, property, this.schemaResolution, context); if (reResolvedProperty.isPresent()) { property = reResolvedProperty.get(); } reResolvedProperty = AnnotationsUtils.getArraySchema(ctxArraySchema, annotatedType.getComponents(), null, openapi31, property); if (reResolvedProperty.isPresent()) { property = reResolvedProperty.get(); } } } } else if (property.get$ref() != null) { if (applySchemaResolution()) { if (Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) && ctxProperty != null) { property = new Schema() .addAllOfItem(ctxProperty) .addAllOfItem(new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName())); } else if (Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution) && ctxProperty != null) { property = ctxProperty .addAllOfItem(new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName())); } else { property = new Schema().$ref(StringUtils.isNotEmpty(property.get$ref()) ? property.get$ref() : property.getName()); } } else { if (StringUtils.isEmpty(property.get$ref())) { property.$ref(property.getName()); } } } } property.setName(propName); JAXBAnnotationsHelper.apply(propBeanDesc.getClassInfo(), annotations, property); if (property != null && io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED.equals(requiredMode)) { addRequiredItem(model, property.getName()); } if (ctxProperty == null) { ctxProperty = property; } final boolean applyNotNullAnnotations = io.swagger.v3.oas.annotations.media.Schema.RequiredMode.AUTO.equals(requiredMode); annotations = addGenericTypeArgumentAnnotationsForOptionalField(propDef, annotations); applyBeanValidatorAnnotations(propDef, ctxProperty, annotations, model, applyNotNullAnnotations); props.add(property); } } } for (Schema prop : props) { modelProps.put(prop.getName(), prop); } if (modelProps.size() > 0) { if (model.getProperties() == null) { model.setProperties(modelProps); } else { for (String key : modelProps.keySet()) { model.addProperty(key, modelProps.get(key)); } } for (String propName : requiredProps) { addRequiredItem(model, propName); } } /** * --Preventing parent/child hierarchy creation loops - Comment 2-- * Creating a parent model will result in the creation of child models, as per the first If statement following * this comment. Creating a child model will result in the creation of a parent model, as per the second If * statement following this comment. * * The current model must be defined in the context immediately. This done to help prevent repeated * loops where parents create children and children create parents when a hierarchy is present. This logic * works in conjunction with the "early checking" performed earlier in this method * (See "Preventing parent/child hierarchy creation loops - Comment 1"), to prevent repeated creation loops. * * * As an aside, defining the current model in the context immediately also ensures that child models are * available for modification by resolveSubtypes, when their parents are created. */ if (!type.isContainerType() && StringUtils.isNotBlank(name)) { context.defineModel(name, model, annotatedType, null); } /** * This must be done after model.setProperties so that the model's set * of properties is available to filter from any subtypes **/ if (!resolveSubtypes(model, beanDesc, context, annotatedType.getJsonViewAnnotation())) { model.setDiscriminator(null); } Discriminator discriminator = resolveDiscriminator(type, context); if (discriminator != null) { model.setDiscriminator(discriminator); } if (resolvedSchemaAnnotation != null) { String ref = resolvedSchemaAnnotation.ref(); // consider ref as is if (!StringUtils.isBlank(ref)) { model.$ref(ref); } Class not = resolvedSchemaAnnotation.not(); if (!Void.class.equals(not)) { model.not((new Schema().$ref(context.resolve(new AnnotatedType().components(annotatedType.getComponents()).type(not).jsonViewAnnotation(annotatedType.getJsonViewAnnotation())).getName()))); } if (resolvedSchemaAnnotation.requiredProperties() != null && resolvedSchemaAnnotation.requiredProperties().length > 0 && StringUtils.isNotBlank(resolvedSchemaAnnotation.requiredProperties()[0])) { for (String prop : resolvedSchemaAnnotation.requiredProperties()) { addRequiredItem(model, prop); } } } Map patternProperties = resolvePatternProperties(type, annotatedType.getCtxAnnotations(), context); if (model != null && patternProperties != null && !patternProperties.isEmpty()) { if (model.getPatternProperties() == null) { model.patternProperties(patternProperties); } else { model.getPatternProperties().putAll(patternProperties); } } Map schemaProperties = resolveSchemaProperties(type, annotatedType.getCtxAnnotations(), context); if (model != null && schemaProperties != null && !schemaProperties.isEmpty()) { if (model.getProperties() == null) { model.properties(schemaProperties); } else { model.getProperties().putAll(schemaProperties); } } if (openapi31) { Map dependentSchemas = resolveDependentSchemas(type, annotatedType.getCtxAnnotations(), context, annotatedType.getComponents(), annotatedType.getJsonViewAnnotation(), openapi31); if (model != null && dependentSchemas != null && !dependentSchemas.isEmpty()) { if (model.getDependentSchemas() == null) { model.dependentSchemas(dependentSchemas); } else { model.getDependentSchemas().putAll(dependentSchemas); } } } if (hasCompositionKeywords) { Schema schemaWithCompositionKeys = model; Class[] allOf = resolvedSchemaAnnotation.allOf(); Class[] anyOf = resolvedSchemaAnnotation.anyOf(); Class[] oneOf = resolvedSchemaAnnotation.oneOf(); List> allOfFiltered = Stream.of(allOf) .distinct() .filter(c -> !this.shouldIgnoreClass(c)) .filter(c -> !(c.equals(Void.class))) .collect(Collectors.toList()); allOfFiltered.forEach(c -> { Schema allOfRef = context.resolve(new AnnotatedType().components(annotatedType.getComponents()).type(c).jsonViewAnnotation(annotatedType.getJsonViewAnnotation())); Schema refSchema = new Schema().$ref(Components.COMPONENTS_SCHEMAS_REF + allOfRef.getName()); if (StringUtils.isBlank(allOfRef.getName())) { refSchema = allOfRef; } // allOf could have already being added during subtype resolving if (schemaWithCompositionKeys.getAllOf() == null || !schemaWithCompositionKeys.getAllOf().contains(refSchema)) { schemaWithCompositionKeys.addAllOfItem(refSchema); } // remove shared properties defined in the parent if (isSubtype(beanDesc.getClassInfo(), c)) { removeParentProperties(schemaWithCompositionKeys, allOfRef); } }); List> anyOfFiltered = Stream.of(anyOf) .distinct() .filter(c -> !this.shouldIgnoreClass(c)) .filter(c -> !(c.equals(Void.class))) .collect(Collectors.toList()); anyOfFiltered.forEach(c -> { Schema anyOfRef = context.resolve(new AnnotatedType().components(annotatedType.getComponents()).type(c).jsonViewAnnotation(annotatedType.getJsonViewAnnotation())); if (anyOfRef != null) { if (StringUtils.isNotBlank(anyOfRef.getName())) { schemaWithCompositionKeys.addAnyOfItem(new Schema().$ref(Components.COMPONENTS_SCHEMAS_REF + anyOfRef.getName())); } else { schemaWithCompositionKeys.addAnyOfItem(anyOfRef); } } // remove shared properties defined in the parent if (isSubtype(beanDesc.getClassInfo(), c)) { removeParentProperties(schemaWithCompositionKeys, anyOfRef); } }); List> oneOfFiltered = Stream.of(oneOf) .distinct() .filter(c -> !this.shouldIgnoreClass(c)) .filter(c -> !(c.equals(Void.class))) .collect(Collectors.toList()); oneOfFiltered.forEach(c -> { Schema oneOfRef = context.resolve(new AnnotatedType().components(annotatedType.getComponents()).type(c).jsonViewAnnotation(annotatedType.getJsonViewAnnotation())); if (oneOfRef != null) { if (StringUtils.isBlank(oneOfRef.getName())) { schemaWithCompositionKeys.addOneOfItem(oneOfRef); } else { schemaWithCompositionKeys.addOneOfItem(new Schema().$ref(Components.COMPONENTS_SCHEMAS_REF + oneOfRef.getName())); } // remove shared properties defined in the parent if (isSubtype(beanDesc.getClassInfo(), c)) { removeParentProperties(schemaWithCompositionKeys, oneOfRef); } } dropRootRefIfComposed(schemaWithCompositionKeys); }); if (!composedModelPropertiesAsSibling) { if (schemaWithCompositionKeys.getAllOf() != null && !schemaWithCompositionKeys.getAllOf().isEmpty()) { if (schemaWithCompositionKeys.getProperties() != null && !schemaWithCompositionKeys.getProperties().isEmpty()) { Schema propSchema = openapi31 ? new JsonSchema().typesItem("object") : new ObjectSchema(); propSchema.properties(schemaWithCompositionKeys.getProperties()); schemaWithCompositionKeys.setProperties(null); schemaWithCompositionKeys.addAllOfItem(propSchema); } } } } if (!type.isContainerType() && StringUtils.isNotBlank(name)) { // define the model here to support self/cyclic referencing of models context.defineModel(name, model, annotatedType, null); } // check if it has "object" related keywords if (isInferredObjectSchema(model) && model.get$ref() == null) { if (openapi31 && model.getTypes() == null) { model.addType("object"); } else if (!openapi31 && model.getType() == null){ model.type("object"); } } Schema.SchemaResolution resolvedSchemaResolution = AnnotationsUtils.resolveSchemaResolution(this.schemaResolution, resolvedSchemaAnnotation); if (model != null && annotatedType.isResolveAsRef() && (hasCompositionKeywords || isObjectSchema(model) || implicitObject) && StringUtils.isNotBlank(model.getName())) { if (context.getDefinedModels().containsKey(model.getName())) { if (!Schema.SchemaResolution.INLINE.equals(resolvedSchemaResolution)) { model = new Schema().$ref(constructRef(model.getName())); } } } else if (model != null && model.get$ref() != null) { model = new Schema().$ref(StringUtils.isNotEmpty(model.get$ref()) ? model.get$ref() : model.getName()); } if (model != null && resolvedArrayAnnotation != null) { if (!"array".equals(model.getType())) { ArraySchema schema = new ArraySchema(); if (openapi31) { schema.specVersion(SpecVersion.V31); } schema.setItems(model); resolveArraySchema(annotatedType, schema, resolvedArrayAnnotation); return schema; } else { if (isArraySchema(model)) { resolveArraySchema(annotatedType, (ArraySchema) model, resolvedArrayAnnotation); } } } resolveDiscriminatorProperty(type, context, model); model = resolveWrapping(type, context, model); return model; } private Annotation[] addGenericTypeArgumentAnnotationsForOptionalField(BeanPropertyDefinition propDef, Annotation[] annotations) { boolean isNotOptionalType = Optional.ofNullable(propDef) .map(BeanPropertyDefinition::getField) .map(AnnotatedField::getAnnotated) .map(field -> !(field.getType().equals(Optional.class))) .orElse(false); if (isNotOptionalType || isRecordType(propDef)) { return annotations; } Stream genericTypeArgumentAnnotations = extractGenericTypeArgumentAnnotations(propDef); return Stream.concat(Stream.of(annotations), genericTypeArgumentAnnotations).toArray(Annotation[]::new); } private Stream extractGenericTypeArgumentAnnotations(BeanPropertyDefinition propDef) { if (isRecordType(propDef)) { return getRecordComponentAnnotations(propDef); } return Optional.ofNullable(propDef) .map(BeanPropertyDefinition::getField) .map(AnnotatedField::getAnnotated) .map(this::getGenericTypeArgumentAnnotations) .orElseGet(Stream::of); } private Stream getRecordComponentAnnotations(BeanPropertyDefinition propDef) { try { Method accessor = propDef.getPrimaryMember().getDeclaringClass().getDeclaredMethod(propDef.getPrimaryMember().getName()); return getGenericTypeArgumentAnnotations(accessor.getAnnotatedReturnType()); } catch (NoSuchMethodException e) { LOGGER.error("Accessor for record component not found"); return Stream.empty(); } } private void dropRootRefIfComposed(Schema s) { if (s == null || s.get$ref() == null) { return; } if (!isComposedSchema(s)) { return; } String ref = s.get$ref(); if (refMatchesAnyComposedItem(s, ref)) { s.set$ref(null); } } private boolean isComposedSchema(Schema s) { return (s.getOneOf() != null && !s.getOneOf().isEmpty()) || (s.getAnyOf() != null && !s.getAnyOf().isEmpty()) || (s.getAllOf() != null && !s.getAllOf().isEmpty()); } private boolean refMatchesAnyComposedItem(Schema s, String ref) { return refMatchesInList(s.getOneOf(), ref) || refMatchesInList(s.getAllOf(), ref) || refMatchesInList(s.getAnyOf(), ref); } private boolean refMatchesInList(List schemas, String ref) { return schemas != null && schemas.stream() .anyMatch(schema -> ref.equals(schema.get$ref())); } private Boolean isRecordType(BeanPropertyDefinition propDef) { try { if (propDef.getPrimaryMember() != null) { Class clazz = propDef.getPrimaryMember().getDeclaringClass(); Method isRecordMethod = Class.class.getMethod("isRecord"); return (Boolean) isRecordMethod.invoke(clazz); } else { return false; } } catch (NoSuchMethodException e) { return false; } catch (Exception e) { return false; } } private Stream getGenericTypeArgumentAnnotations(Field field) { return getGenericTypeArgumentAnnotations(field.getAnnotatedType()); } private Stream getGenericTypeArgumentAnnotations(java.lang.reflect.AnnotatedType annotatedType) { return Optional.of(annotatedType) .filter(type -> type instanceof AnnotatedParameterizedType) .map(type -> (AnnotatedParameterizedType) type) .map(AnnotatedParameterizedType::getAnnotatedActualTypeArguments) .map(types -> Stream.of(types) .flatMap(type -> Stream.of(type.getAnnotations()))) .orElseGet(Stream::of); } private boolean shouldResolveEnumAsRef(io.swagger.v3.oas.annotations.media.Schema resolvedSchemaAnnotation, boolean isResolveEnumAsRef) { return (resolvedSchemaAnnotation != null && resolvedSchemaAnnotation.enumAsRef()) || ModelResolver.enumsAsRef || isResolveEnumAsRef; } protected Type findJsonValueType(final BeanDescription beanDesc) { // use recursion to check for method findJsonValueAccessor existence (Jackson 2.9+) // if not found use previous deprecated method which could lead to inaccurate result try { AnnotatedMember jsonValueMember = invokeMethod(beanDesc, "findJsonValueAccessor"); if (jsonValueMember != null) { return jsonValueMember.getType(); } return null; } catch (Exception e) { LOGGER.warn("jackson BeanDescription.findJsonValueAccessor not found, this could lead to inaccurate result, please update jackson to 2.9+"); } try { AnnotatedMember jsonValueMember = invokeMethod(beanDesc, "findJsonValueMethod"); if (jsonValueMember != null) { return jsonValueMember.getType(); } } catch (Exception e) { LOGGER.error("Neither 'findJsonValueMethod' nor 'findJsonValueAccessor' found in jackson BeanDescription. Please verify your Jackson version."); } return null; } private Schema clone(Schema property) { return AnnotationsUtils.clone(property, openapi31); } private boolean isSubtype(AnnotatedClass childClass, Class parentClass) { final BeanDescription parentDesc = _mapper.getSerializationConfig().introspectClassAnnotations(parentClass); List subTypes = _intr().findSubtypes(parentDesc.getClassInfo()); if (subTypes == null) { return false; } for (NamedType subtype : subTypes) { final Class subtypeType = subtype.getType(); if (childClass.getRawType().isAssignableFrom(subtypeType)) { return true; } } return false; } protected boolean _isOptionalType(JavaType propType) { return Arrays.asList("com.google.common.base.Optional", "java.util.Optional") .contains(propType.getRawClass().getCanonicalName()); } /** * @deprecated use '_createSchemaForEnum' */ protected void _addEnumProps(Class propClass, Schema property) { if (propClass.isEnum()) { Class> rawEnumClass = (Class>) propClass; Schema enumSchema = _createSchemaForEnum(rawEnumClass); if (enumSchema != null) { property.setEnum(enumSchema.getEnum()); property.setType(enumSchema.getType()); property.setFormat(enumSchema.getFormat()); property.setName(enumSchema.getName()); property.setDescription(enumSchema.getDescription()); } } } /** * Adds each enum property value to the model schema * * @param enumClass the enum class for which to add properties */ protected Schema _createSchemaForEnum(Class> enumClass) { boolean useIndex = _mapper.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX); boolean useToString = _mapper.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); Optional jsonValueMethod = Arrays.stream(enumClass.getDeclaredMethods()) .filter(m -> m.isAnnotationPresent(JsonValue.class)) .filter(m -> m.getAnnotation(JsonValue.class).value()) .findFirst(); Optional jsonValueField = Arrays.stream(enumClass.getDeclaredFields()) .filter(f -> f.isAnnotationPresent(JsonValue.class)) .filter(f -> f.getAnnotation(JsonValue.class).value()) .findFirst(); Schema schema = null; if (jsonValueField.isPresent()) { jsonValueField.get().setAccessible(true); PrimitiveType primitiveType = PrimitiveType.fromType(jsonValueField.get().getType()); if (primitiveType != null) { schema = openapi31 ? primitiveType.createProperty31() : primitiveType.createProperty(); } } else if (jsonValueMethod.isPresent()) { jsonValueMethod.get().setAccessible(true); PrimitiveType primitiveType = PrimitiveType.fromType(jsonValueMethod.get().getReturnType()); if (primitiveType != null) { schema = openapi31 ? primitiveType.createProperty31() : primitiveType.createProperty(); } } if (schema == null) { schema = openapi31 ? new JsonSchema().typesItem("string") : new StringSchema(); } Enum[] enumConstants = enumClass.getEnumConstants(); if (enumConstants != null) { String[] enumValues = _intr().findEnumValues(enumClass, enumConstants, new String[enumConstants.length]); for (Enum en : enumConstants) { Field enumField = ReflectionUtils.findField(en.name(), enumClass); if (null != enumField && enumField.isAnnotationPresent(Hidden.class)) { continue; } String enumValue = enumValues[en.ordinal()]; Object methodValue = jsonValueMethod.flatMap(m -> ReflectionUtils.safeInvoke(m, en)).orElse(null); Object fieldValue = jsonValueField.flatMap(f -> ReflectionUtils.safeGet(f, en)).orElse(null); Object n; if (methodValue != null) { n = methodValue; } else if (fieldValue != null) { n = fieldValue; } else if (enumValue != null) { n = enumValue; } else if (useIndex) { n = String.valueOf(en.ordinal()); } else if (useToString) { n = en.toString(); } else { n = _intr().findEnumValue(en); } schema.addEnumItemObject(n); } } return schema; } protected boolean ignore(final Annotated member, final XmlAccessorType xmlAccessorTypeAnnotation, final String propName, final Set propertiesToIgnore) { return ignore(member, xmlAccessorTypeAnnotation, propName, propertiesToIgnore, null); } protected boolean hasHiddenAnnotation(Annotated annotated) { return annotated.hasAnnotation(Hidden.class) || ( annotated.hasAnnotation(io.swagger.v3.oas.annotations.media.Schema.class) && annotated.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class).hidden() ); } protected boolean ignore(final Annotated member, final XmlAccessorType xmlAccessorTypeAnnotation, final String propName, final Set propertiesToIgnore, BeanPropertyDefinition propDef) { if (propertiesToIgnore.contains(propName)) { return true; } if (member.hasAnnotation(JsonIgnore.class) && member.getAnnotation(JsonIgnore.class).value()) { return true; } if (hasHiddenAnnotation(member)) { return true; } if (propDef != null) { if (propDef.hasGetter() && hasHiddenAnnotation(propDef.getGetter())) { return true; } if (propDef.hasSetter() && hasHiddenAnnotation(propDef.getSetter())) { return true; } if (propDef.hasConstructorParameter() && hasHiddenAnnotation(propDef.getConstructorParameter())) { return true; } if (propDef.hasField() && hasHiddenAnnotation(propDef.getField())) { return true; } } if (xmlAccessorTypeAnnotation == null) { return false; } if (xmlAccessorTypeAnnotation.value().equals(XmlAccessType.NONE)) { if (!member.hasAnnotation(XmlElement.class) && !member.hasAnnotation(XmlAttribute.class) && !member.hasAnnotation(XmlElementRef.class) && !member.hasAnnotation(XmlElementRefs.class) && !member.hasAnnotation(JsonProperty.class)) { return true; } } return false; } private void handleUnwrapped(List props, Schema innerModel, String prefix, String suffix, List requiredProps) { if (StringUtils.isBlank(suffix) && StringUtils.isBlank(prefix)) { if (innerModel.getProperties() != null) { props.addAll(innerModel.getProperties().values()); if (innerModel.getRequired() != null) { requiredProps.addAll(innerModel.getRequired()); } } } else { if (prefix == null) { prefix = ""; } if (suffix == null) { suffix = ""; } if (innerModel.getProperties() != null) { for (Schema prop : (Collection) innerModel.getProperties().values()) { try { Schema clonedProp = Json.mapper().readValue(Json.pretty(prop), Schema.class); clonedProp.setName(prefix + prop.getName() + suffix); props.add(clonedProp); } catch (IOException e) { LOGGER.error("Exception cloning property", e); return; } } } } } public Schema.SchemaResolution getSchemaResolution() { return schemaResolution; } public void setSchemaResolution(Schema.SchemaResolution schemaResolution) { this.schemaResolution = schemaResolution; } public ModelResolver schemaResolution(Schema.SchemaResolution schemaResolution) { setSchemaResolution(schemaResolution); return this; } private class GeneratorWrapper { private final List wrappers = new ArrayList(); private final class PropertyGeneratorWrapper extends GeneratorWrapper.Base { public PropertyGeneratorWrapper(Class generator) { super(generator); } @Override protected Schema processAsProperty(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper) { /* * When generator = ObjectIdGenerators.PropertyGenerator.class and * @JsonIdentityReference(alwaysAsId = false) then property is serialized * in the same way it is done without @JsonIdentityInfo annotation. */ return null; } @Override protected Schema processAsId(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper) { final JavaType javaType; if (type.getType() instanceof JavaType) { javaType = (JavaType) type.getType(); } else { javaType = mapper.constructType(type.getType()); } final BeanDescription beanDesc = mapper.getSerializationConfig().introspect(javaType); for (BeanPropertyDefinition def : beanDesc.findProperties()) { final String name = def.getName(); if (name != null && name.equals(propertyName)) { final AnnotatedMember propMember = def.getPrimaryMember(); final JavaType propType = propMember.getType(); if (PrimitiveType.fromType(propType) != null) { return PrimitiveType.createProperty(propType, openapi31); } else { List list = new ArrayList<>(); for (Annotation a : propMember.annotations()) { list.add(a); } Annotation[] annotations = list.toArray(new Annotation[list.size()]); AnnotatedType aType = new AnnotatedType() .type(propType) .ctxAnnotations(annotations) .jsonViewAnnotation(type.getJsonViewAnnotation()) .schemaProperty(true) .components(type.getComponents()) .subtype(type.isSubtype()) .propertyName(type.getPropertyName()); return context.resolve(aType); } } } return null; } } private final class IntGeneratorWrapper extends GeneratorWrapper.Base { public IntGeneratorWrapper(Class generator) { super(generator); } @Override protected Schema processAsProperty(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper) { Schema id = new IntegerSchema(); return process(id, propertyName, type, context); } @Override protected Schema processAsId(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper) { return new IntegerSchema(); } } private final class UUIDGeneratorWrapper extends GeneratorWrapper.Base { public UUIDGeneratorWrapper(Class generator) { super(generator); } @Override protected Schema processAsProperty(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper) { Schema id = new UUIDSchema(); return process(id, propertyName, type, context); } @Override protected Schema processAsId(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper) { return new UUIDSchema(); } } private final class NoneGeneratorWrapper extends GeneratorWrapper.Base { public NoneGeneratorWrapper(Class generator) { super(generator); } // When generator = ObjectIdGenerators.None.class property should be processed as normal property. @Override protected Schema processAsProperty(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper) { return null; } @Override protected Schema processAsId(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper) { return null; } } private abstract class Base { private final Class generator; Base(Class generator) { this.generator = generator; } protected abstract Schema processAsProperty(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper); protected abstract Schema processAsId(String propertyName, AnnotatedType type, ModelConverterContext context, ObjectMapper mapper); } public Schema processJsonIdentity(AnnotatedType type, ModelConverterContext context, ObjectMapper mapper, JsonIdentityInfo identityInfo, JsonIdentityReference identityReference) { final GeneratorWrapper.Base wrapper = identityInfo != null ? getWrapper(identityInfo.generator()) : null; if (wrapper == null) { return null; } if (identityReference != null && identityReference.alwaysAsId()) { return wrapper.processAsId(identityInfo.property(), type, context, mapper); } else { return wrapper.processAsProperty(identityInfo.property(), type, context, mapper); } } private GeneratorWrapper.Base getWrapper(Class generator) { if (ObjectIdGenerators.PropertyGenerator.class.isAssignableFrom(generator)) { return new PropertyGeneratorWrapper(generator); } else if (ObjectIdGenerators.IntSequenceGenerator.class.isAssignableFrom(generator)) { return new IntGeneratorWrapper(generator); } else if (ObjectIdGenerators.UUIDGenerator.class.isAssignableFrom(generator)) { return new UUIDGeneratorWrapper(generator); } else if (ObjectIdGenerators.None.class.isAssignableFrom(generator)) { return new NoneGeneratorWrapper(generator); } return null; } protected Schema process(Schema id, String propertyName, AnnotatedType type, ModelConverterContext context) { type = removeJsonIdentityAnnotations(type); Schema model = context.resolve(type); if (model == null) { model = resolve(type, context, null); } model.addProperties(propertyName, id); Schema retSchema = openapi31 ? new JsonSchema() : new Schema(); return retSchema.$ref(StringUtils.isNotEmpty(model.get$ref()) ? model.get$ref() : model.getName()); } private AnnotatedType removeJsonIdentityAnnotations(AnnotatedType type) { return new AnnotatedType() .jsonUnwrappedHandler(type.getJsonUnwrappedHandler()) .jsonViewAnnotation(type.getJsonViewAnnotation()) .name(type.getName()) .parent(type.getParent()) .resolveAsRef(false) .schemaProperty(type.isSchemaProperty()) .skipOverride(type.isSkipOverride()) .skipSchemaName(type.isSkipSchemaName()) .type(type.getType()) .skipJsonIdentity(true) .propertyName(type.getPropertyName()) .components(type.getComponents()) .ctxAnnotations(AnnotationsUtils.removeAnnotations(type.getCtxAnnotations(), JsonIdentityInfo.class, JsonIdentityReference.class)); } } protected boolean applyBeanValidatorAnnotations(BeanPropertyDefinition propDef, Schema property, Annotation[] annotations, Schema parent, boolean applyNotNullAnnotations) { boolean updated = false; updated = applyBeanValidatorAnnotations(property, annotations, parent, applyNotNullAnnotations); if (Objects.nonNull(property.getItems())) { Annotation[] genericTypeArgumentAnnotations = extractGenericTypeArgumentAnnotations(propDef).toArray(Annotation[]::new); updated = applyBeanValidatorAnnotations(property.getItems(), genericTypeArgumentAnnotations, property, applyNotNullAnnotations) || updated; } return updated; } protected Configuration.GroupsValidationStrategy resolveGroupsValidationStrategy() { return configuration == null ? Configuration.GroupsValidationStrategy.DEFAULT : configuration.getGroupsValidationStrategy(); } protected Set resolveValidationInvocationGroups(Map annos) { Set invocationGroups = new LinkedHashSet<>(); if (annos.containsKey("org.springframework.validation.annotation.Validated")) { Annotation validated = annos.get("org.springframework.validation.annotation.Validated"); Method method = null; try { method = validated.getClass().getDeclaredMethod("value"); Class[] groups = (Class[]) method.invoke(validated, null); invocationGroups.addAll(Arrays.asList(groups)); } catch (Exception e) { // } } if (annos.containsKey("io.swagger.v3.oas.annotations.parameters.ValidatedParameter")) { Annotation validated = annos.get("io.swagger.v3.oas.annotations.parameters.ValidatedParameter"); Method method = null; try { method = validated.getClass().getDeclaredMethod("value"); Class[] groups = (Class[]) method.invoke(validated, null); invocationGroups.addAll(Arrays.asList(groups)); } catch (Exception e) { // } } if (annos.containsKey("io.swagger.v3.oas.annotations.Parameter")) { Parameter parameter = (Parameter) annos.get("io.swagger.v3.oas.annotations.Parameter"); invocationGroups.addAll(Arrays.asList(parameter.validationGroups())); } return invocationGroups; } protected Set resolveValidationInvocationAnnotations(Annotation[] annotations) { Set validationInvocationAnnotations = new LinkedHashSet<>(); if (annotations == null) { return validationInvocationAnnotations; } for (Annotation anno : annotations) { if (anno.annotationType().getName().equals("org.springframework.validation.annotation.Validated")) { validationInvocationAnnotations.add(anno); } if (anno.annotationType().getName().equals("io.swagger.v3.oas.annotations.parameters.ValidatedParameter")) { validationInvocationAnnotations.add(anno); } if (anno.annotationType().getName().equals("io.swagger.v3.oas.annotations.Parameter")) { validationInvocationAnnotations.add(anno); } } return validationInvocationAnnotations; } protected boolean applyBeanValidatorAnnotations(Schema property, Annotation[] annotations, Schema parent, boolean applyNotNullAnnotations) { boolean modified = false; Configuration.GroupsValidationStrategy strategy = resolveGroupsValidationStrategy(); if (strategy.equals(Configuration.GroupsValidationStrategy.ALWAYS)) { return applyBeanValidatorAnnotationsNoGroups(property, annotations, parent, applyNotNullAnnotations); } else if (strategy.equals(Configuration.GroupsValidationStrategy.NEVER)) { return modified; } if (validatorProcessor != null && (validatorProcessor.getMode().equals(ValidatorProcessor.MODE.BEFORE) || validatorProcessor.getMode().equals(ValidatorProcessor.MODE.REPLACE))) { modified = validatorProcessor.applyBeanValidatorAnnotations(property, annotations, parent, applyNotNullAnnotations); if (validatorProcessor.getMode().equals(ValidatorProcessor.MODE.REPLACE)) { return modified; } } Map annos = new HashMap<>(); if (annotations != null) { for (Annotation anno : annotations) { annos.put(anno.annotationType().getName(), anno); } } if (parent != null && Arrays.stream(annotations).anyMatch( annotation -> annotation.annotationType().getSimpleName().equalsIgnoreCase("NonNull"))) { modified = updateRequiredItem(parent, property.getName()) || modified; } // see if we have Validated or other group-aware annotations Set invocationGroups = null; if (validatorProcessor != null) { invocationGroups = validatorProcessor.resolveInvocationGroups(annos); } if (invocationGroups == null) { invocationGroups = resolveValidationInvocationGroups(annos); } if (invocationGroups.isEmpty()) { if (strategy.equals(Configuration.GroupsValidationStrategy.NEVER_IF_NO_CONTEXT)) { return modified; } } else { if (!(strategy.equals(Configuration.GroupsValidationStrategy.DEFAULT) || strategy.equals(Configuration.GroupsValidationStrategy.NEVER_IF_NO_CONTEXT))) { return modified; } } boolean acceptNoGroups = !strategy.equals(Configuration.GroupsValidationStrategy.NEVER_IF_NO_CONTEXT); // if we get here, validate only if groups match. if (parent != null && annos.containsKey(JAVAX_NOT_NULL) && applyNotNullAnnotations) { NotNull anno = (NotNull) annos.get(JAVAX_NOT_NULL); if (anno.groups().length == 0 && acceptNoGroups) { ; // no groups, so apply modified = updateRequiredItem(parent, property.getName()) || modified; } else { // check if the groups match for (Class group : anno.groups()) { if (invocationGroups.contains(group)) { modified = updateRequiredItem(parent, property.getName()) || modified; } } } } if (annos.containsKey(JAVAX_NOT_EMPTY)) { NotEmpty anno = (NotEmpty) annos.get(JAVAX_NOT_EMPTY); boolean apply = checkGroupValidation(anno.groups(), invocationGroups, acceptNoGroups); if (apply) { io.swagger.v3.oas.annotations.media.Schema ctxSchema = AnnotationsUtils.getSchemaAnnotation(annotations); io.swagger.v3.oas.annotations.media.ArraySchema ctxArraySchema = AnnotationsUtils.getArraySchemaAnnotation(annotations); modified = ValidationAnnotationsUtils.applyNotEmptyConstraint(property, ctxSchema, ctxArraySchema) || modified; if (applyNotNullAnnotations) { modified = updateRequiredItem(parent, property.getName()) || modified; } } } if (annos.containsKey(JAVAX_NOT_BLANK)) { NotBlank anno = (NotBlank) annos.get(JAVAX_NOT_BLANK); boolean apply = checkGroupValidation(anno.groups(), invocationGroups, acceptNoGroups); if (apply) { io.swagger.v3.oas.annotations.media.Schema ctxSchema = AnnotationsUtils.getSchemaAnnotation(annotations); modified = ValidationAnnotationsUtils.applyNotBlankConstraint(property, ctxSchema) || modified; if (applyNotNullAnnotations) { modified = updateRequiredItem(parent, property.getName()) || modified; } } } if (annos.containsKey(JAVAX_MIN)) { Min anno = (Min) annos.get(JAVAX_MIN); boolean apply = checkGroupValidation(anno.groups(), invocationGroups, acceptNoGroups); if (apply) { modified = ValidationAnnotationsUtils.applyMinConstraint(property, anno) || modified; } } if (annos.containsKey(JAVAX_MAX)) { Max anno = (Max) annos.get(JAVAX_MAX); boolean apply = checkGroupValidation(anno.groups(), invocationGroups, acceptNoGroups); if (apply) { modified = ValidationAnnotationsUtils.applyMaxConstraint(property, anno) || modified; } } if (annos.containsKey(JAVAX_SIZE)) { Size anno = (Size) annos.get(JAVAX_SIZE); boolean apply = checkGroupValidation(anno.groups(), invocationGroups, acceptNoGroups); if (apply) { modified = ValidationAnnotationsUtils.applySizeConstraint(property, anno) || modified; } } if (annos.containsKey(JAVAX_DECIMAL_MIN)) { DecimalMin min = (DecimalMin) annos.get(JAVAX_DECIMAL_MIN); boolean apply = checkGroupValidation(min.groups(), invocationGroups, acceptNoGroups); if (apply) { modified = ValidationAnnotationsUtils.applyDecimalMinConstraint(property, min) || modified; } } if (annos.containsKey(JAVAX_DECIMAL_MAX)) { DecimalMax max = (DecimalMax) annos.get(JAVAX_DECIMAL_MAX); boolean apply = checkGroupValidation(max.groups(), invocationGroups, acceptNoGroups); if (apply) { modified = ValidationAnnotationsUtils.applyDecimalMaxConstraint(property, max) || modified; } } if (annos.containsKey(JAVAX_PATTERN)) { Pattern pattern = (Pattern) annos.get(JAVAX_PATTERN); boolean apply = checkGroupValidation(pattern.groups(), invocationGroups, acceptNoGroups); if (apply) { modified = ValidationAnnotationsUtils.applyPatternConstraint(property, pattern) || modified; } } if (annos.containsKey(JAVAX_EMAIL)) { Email email = (Email) annos.get(JAVAX_EMAIL); boolean apply = checkGroupValidation(email.groups(), invocationGroups, acceptNoGroups); if (apply) { modified = ValidationAnnotationsUtils.applyEmailConstraint(property, email) || modified; } } if (validatorProcessor != null && validatorProcessor.getMode().equals(ValidatorProcessor.MODE.AFTER)) { modified = validatorProcessor.applyBeanValidatorAnnotations(property, annotations, parent, applyNotNullAnnotations) || modified; } return modified; } protected boolean checkGroupValidation(Class[] groups, Set invocationGroups, boolean acceptNoGroups) { if (groups.length == 0) { return acceptNoGroups; } else { for (Class group : groups) { if (invocationGroups.contains(group)) { return true; } } } return false; } protected boolean applyBeanValidatorAnnotationsNoGroups(Schema property, Annotation[] annotations, Schema parent, boolean applyNotNullAnnotations) { Map annos = new HashMap<>(); boolean modified = false; if (annotations != null) { for (Annotation anno : annotations) { annos.put(anno.annotationType().getName(), anno); } } if (parent != null && annotations != null && applyNotNullAnnotations) { boolean requiredItem = Arrays.stream(annotations).anyMatch(annotation -> NOT_NULL_ANNOTATIONS.contains(annotation.annotationType().getSimpleName()) ); if (requiredItem) { modified = updateRequiredItem(parent, property.getName()); } } if (annos.containsKey(JAVAX_MIN)) { Min min = (Min) annos.get(JAVAX_MIN); modified = ValidationAnnotationsUtils.applyMinConstraint(property, min) || modified; } if (annos.containsKey(JAVAX_MAX)) { Max max = (Max) annos.get(JAVAX_MAX); modified = ValidationAnnotationsUtils.applyMaxConstraint(property, max) || modified; } if (annos.containsKey(JAVAX_SIZE)) { Size size = (Size) annos.get(JAVAX_SIZE); modified = ValidationAnnotationsUtils.applySizeConstraint(property, size) || modified; } if (annos.containsKey(JAVAX_DECIMAL_MIN)) { DecimalMin min = (DecimalMin) annos.get(JAVAX_DECIMAL_MIN); modified = ValidationAnnotationsUtils.applyDecimalMinConstraint(property, min) || modified; } if (annos.containsKey(JAVAX_DECIMAL_MAX)) { DecimalMax max = (DecimalMax) annos.get(JAVAX_DECIMAL_MAX); modified = ValidationAnnotationsUtils.applyDecimalMaxConstraint(property, max) || modified; } if (annos.containsKey(JAVAX_PATTERN)) { Pattern pattern = (Pattern) annos.get(JAVAX_PATTERN); modified = ValidationAnnotationsUtils.applyPatternConstraint(property, pattern) || modified; } if (annos.containsKey(JAVAX_EMAIL)) { Email pattern = (Email) annos.get(JAVAX_EMAIL); modified = ValidationAnnotationsUtils.applyEmailConstraint(property, pattern) || modified; } return modified; } private boolean resolveSubtypes(Schema model, BeanDescription bean, ModelConverterContext context, JsonView jsonViewAnnotation) { final List types = _intr().findSubtypes(bean.getClassInfo()); if (types == null) { return false; } /** * Remove the current class from the child classes. This happens if @JsonSubTypes references * the annotated class as a subtype. */ removeSelfFromSubTypes(types, bean); /** * As the introspector will find @JsonSubTypes for a child class that are present on its super classes, the * code segment below will also run the introspector on the parent class, and then remove any sub-types that are * found for the parent from the sub-types found for the child. The same logic all applies to implemented * interfaces, and is accounted for below. */ removeSuperClassAndInterfaceSubTypes(types, bean); int count = 0; final Class beanClass = bean.getClassInfo().getAnnotated(); for (NamedType subtype : types) { final Class subtypeType = subtype.getType(); if (!beanClass.isAssignableFrom(subtypeType)) { continue; } final Schema subtypeModel = context.resolve(new AnnotatedType() .type(subtypeType) .jsonViewAnnotation(jsonViewAnnotation) .subtype(true)); if (StringUtils.isBlank(subtypeModel.getName()) || subtypeModel.getName().equals(model.getName())) { subtypeModel.setName(_typeNameResolver.nameForType(_mapper.constructType(subtypeType), TypeNameResolver.Options.SKIP_API_MODEL)); } // here schema could be not composed, but we want it to be composed, doing same work as done // in resolve method?? ComposedSchema composedSchema = null; if (!(subtypeModel instanceof ComposedSchema)) { // create composed schema composedSchema = ComposedSchema.from(subtypeModel); } else { composedSchema = (ComposedSchema) subtypeModel; } Schema refSchema = openapi31 ? new JsonSchema() : new Schema(); refSchema.$ref(Components.COMPONENTS_SCHEMAS_REF + model.getName()); // allOf could have already being added during type resolving when @Schema(allOf..) is declared if (composedSchema.getAllOf() == null || !composedSchema.getAllOf().contains(refSchema)) { composedSchema.addAllOfItem(refSchema); } removeParentProperties(composedSchema, model); if (!composedModelPropertiesAsSibling) { if (composedSchema.getAllOf() != null && !composedSchema.getAllOf().isEmpty()) { if (composedSchema.getProperties() != null && !composedSchema.getProperties().isEmpty()) { Schema propSchema = openapi31 ? new JsonSchema().typesItem("object") : new ObjectSchema(); propSchema.properties(composedSchema.getProperties()); composedSchema.setProperties(null); composedSchema.addAllOfItem(propSchema); } } } // replace previous schema.. Class currentType = subtype.getType(); if (StringUtils.isNotBlank(composedSchema.getName())) { context.defineModel(composedSchema.getName(), composedSchema, new AnnotatedType().type(currentType), null); } } return count != 0; } private void removeSelfFromSubTypes(List types, BeanDescription bean) { Class beanClass = bean.getType().getRawClass(); types.removeIf(type -> beanClass.equals(type.getType())); } private void removeSuperClassAndInterfaceSubTypes(List types, BeanDescription bean) { Class beanClass = bean.getType().getRawClass(); Class superClass = beanClass.getSuperclass(); if (superClass != null && !superClass.equals(Object.class)) { removeSuperSubTypes(types, superClass); } if (!types.isEmpty()) { Class[] superInterfaces = beanClass.getInterfaces(); for (Class superInterface : superInterfaces) { removeSuperSubTypes(types, superInterface); if (types.isEmpty()) { break; } } } } private void removeSuperSubTypes(List resultTypes, Class superClass) { JavaType superType = _mapper.constructType(superClass); BeanDescription superBean = _mapper.getSerializationConfig().introspect(superType); final List superTypes = _intr().findSubtypes(superBean.getClassInfo()); if (superTypes != null) { resultTypes.removeAll(superTypes); } } private void removeParentProperties(Schema child, Schema parent) { final Map baseProps = parent.getProperties(); final Map subtypeProps = child.getProperties(); if (baseProps != null && subtypeProps != null) { for (Map.Entry entry : baseProps.entrySet()) { if (entry.getValue().equals(subtypeProps.get(entry.getKey()))) { subtypeProps.remove(entry.getKey()); } } } if (subtypeProps == null || subtypeProps.isEmpty()) { child.setProperties(null); } } protected List> getComposedSchemaReferencedClasses(Class clazz, Annotation[] ctxAnnotations, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation) { if (schemaAnnotation != null) { Class[] allOf = schemaAnnotation.allOf(); Class[] anyOf = schemaAnnotation.anyOf(); Class[] oneOf = schemaAnnotation.oneOf(); // try to read all of them anyway and resolve? List> parentClasses = Stream.of(allOf, anyOf, oneOf) .flatMap(Stream::of) .distinct() .filter(c -> !this.shouldIgnoreClass(c)) .filter(c -> !(c.equals(Void.class))) .collect(Collectors.toList()); if (!parentClasses.isEmpty()) { return parentClasses; } } return null; } protected String resolveDescription(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && !"".equals(schema.description())) { return schema.description(); } return null; } protected String resolveTitle(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.title())) { return schema.title(); } return null; } protected String resolveFormat(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.format())) { return schema.format(); } return null; } protected Map resolvePatternProperties(JavaType a, Annotation[] annotations, ModelConverterContext context) { final Map propList = new LinkedHashMap<>(); PatternProperties props = a.getRawClass().getAnnotation(PatternProperties.class); if (props != null && props.value().length > 0) { for (PatternProperty prop : props.value()) { propList.put(prop.regex(), prop); } } PatternProperty singleProp = a.getRawClass().getAnnotation(PatternProperty.class); if (singleProp != null) { propList.put(singleProp.regex(), singleProp); } props = AnnotationsUtils.getAnnotation(PatternProperties.class, annotations); if (props != null && props.value().length > 0) { for (PatternProperty prop : props.value()) { propList.put(prop.regex(), prop); } } singleProp = AnnotationsUtils.getAnnotation(PatternProperty.class, annotations); if (singleProp != null) { propList.put(singleProp.regex(), singleProp); } if (propList.isEmpty()) { return null; } Map patternProperties = new LinkedHashMap<>(); for (PatternProperty prop : propList.values()) { String key = prop.regex(); if (StringUtils.isBlank(key)) { continue; } Annotation[] propAnnotations = new Annotation[]{prop.schema(), prop.array()}; AnnotatedType propType = new AnnotatedType() .type(String.class) .ctxAnnotations(propAnnotations) .resolveAsRef(true); Schema resolvedPropSchema = context.resolve(propType); if (resolvedPropSchema != null) { patternProperties.put(key, resolvedPropSchema); } } return patternProperties; } protected Map resolveSchemaProperties(JavaType a, Annotation[] annotations, ModelConverterContext context) { final Map propList = new LinkedHashMap<>(); SchemaProperties props = a.getRawClass().getAnnotation(SchemaProperties.class); if (props != null && props.value().length > 0) { for (SchemaProperty prop : props.value()) { propList.put(prop.name(), prop); } } SchemaProperty singleProp = a.getRawClass().getAnnotation(SchemaProperty.class); if (singleProp != null) { propList.put(singleProp.name(), singleProp); } props = AnnotationsUtils.getAnnotation(SchemaProperties.class, annotations); if (props != null && props.value().length > 0) { for (SchemaProperty prop : props.value()) { propList.put(prop.name(), prop); } } singleProp = AnnotationsUtils.getAnnotation(SchemaProperty.class, annotations); if (singleProp != null) { propList.put(singleProp.name(), singleProp); } if (propList.isEmpty()) { return null; } Map schemaProperties = new LinkedHashMap<>(); for (SchemaProperty prop : propList.values()) { String key = prop.name(); if (StringUtils.isBlank(key)) { continue; } Annotation[] propAnnotations = new Annotation[]{prop.schema(), prop.array()}; AnnotatedType propType = new AnnotatedType() .type(String.class) .ctxAnnotations(propAnnotations) .resolveAsRef(true); Schema resolvedPropSchema = context.resolve(propType); if (resolvedPropSchema != null) { schemaProperties.put(key, resolvedPropSchema); } } return schemaProperties; } protected Map resolveDependentSchemas(JavaType a, Annotation[] annotations, ModelConverterContext context, Components components, JsonView jsonViewAnnotation, boolean openapi31) { final Map dependentSchemaMap = new LinkedHashMap<>(); DependentSchemas dependentSchemasAnnotation = a.getRawClass().getAnnotation(DependentSchemas.class); if (dependentSchemasAnnotation != null && dependentSchemasAnnotation.value().length > 0) { for (DependentSchema dependentSchemaAnnotation : dependentSchemasAnnotation.value()) { dependentSchemaMap.put(dependentSchemaAnnotation.name(), dependentSchemaAnnotation); } } DependentSchema singleDependentSchema = a.getRawClass().getAnnotation(DependentSchema.class); if (singleDependentSchema != null) { dependentSchemaMap.put(singleDependentSchema.name(), singleDependentSchema); } dependentSchemasAnnotation = AnnotationsUtils.getAnnotation(DependentSchemas.class, annotations); if (dependentSchemasAnnotation != null && dependentSchemasAnnotation.value().length > 0) { for (DependentSchema dependentSchemaAnnotation : dependentSchemasAnnotation.value()) { dependentSchemaMap.put(dependentSchemaAnnotation.name(), dependentSchemaAnnotation); } } singleDependentSchema = AnnotationsUtils.getAnnotation(DependentSchema.class, annotations); if (singleDependentSchema != null) { dependentSchemaMap.put(singleDependentSchema.name(), singleDependentSchema); } if (dependentSchemaMap.isEmpty()) { return null; } Map dependentSchemas = new LinkedHashMap<>(); for (DependentSchema dependentSchemaAnnotation : dependentSchemaMap.values()) { String name = dependentSchemaAnnotation.name(); if (StringUtils.isBlank(name)) { continue; } Annotation[] propAnnotations = new Annotation[]{dependentSchemaAnnotation.schema(), dependentSchemaAnnotation.array()}; Schema existingSchema = null; Optional resolvedPropSchema = AnnotationsUtils.getSchemaFromAnnotation(dependentSchemaAnnotation.schema(), components, jsonViewAnnotation, openapi31, null, Schema.SchemaResolution.DEFAULT, context); if (resolvedPropSchema.isPresent()) { existingSchema = resolvedPropSchema.get(); dependentSchemas.put(name, existingSchema); } resolvedPropSchema = AnnotationsUtils.getArraySchema(dependentSchemaAnnotation.array(), components, jsonViewAnnotation, openapi31, existingSchema); if (resolvedPropSchema.isPresent()) { dependentSchemas.put(name, resolvedPropSchema.get()); } } return dependentSchemas; } protected Object resolveDefaultValue(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && !DEFAULT_SENTINEL.equals(schema.defaultValue())) { try { ObjectMapper mapper = ObjectMapperFactory.buildStrictGenericObjectMapper(); JsonNode node = mapper.readTree(schema.defaultValue()); // Only return null for "null" string when nullable=true if (node.isNull()) { if (schema.nullable()) { return null; } else { // When nullable=false, treat "null" as literal string return schema.defaultValue(); } } return node; } catch (IOException e) { return schema.defaultValue(); } } if (a == null) { return null; } XmlElement elem = a.getAnnotation(XmlElement.class); if (elem == null) { if (annotations != null) { for (Annotation ann : annotations) { if (ann instanceof XmlElement) { elem = (XmlElement) ann; break; } } } } if (elem != null) { if (!elem.defaultValue().isEmpty() && !"\u0000".equals(elem.defaultValue())) { return elem.defaultValue(); } } return null; } protected Object resolveExample(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null) { if (!schema.example().isEmpty()) { try { ObjectMapper mapper = ObjectMapperFactory.buildStrictGenericObjectMapper(); JsonNode node = mapper.readTree(schema.example()); if (node.isNull()) { if (schema.nullable()) { return null; } else { return schema.example(); } } return node; } catch (IOException e) { return schema.example(); } } } return null; } /** * Resolve the required mode for a schema based upon the schema annotation. * * @param schema A schema annotation * @return The resolved required mode for the schema */ protected io.swagger.v3.oas.annotations.media.Schema.RequiredMode resolveRequiredMode(io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && !schema.requiredMode().equals(io.swagger.v3.oas.annotations.media.Schema.RequiredMode.AUTO)) { return schema.requiredMode(); } else if (schema != null && schema.required()) { return io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; } return io.swagger.v3.oas.annotations.media.Schema.RequiredMode.AUTO; } /** * Resolve the required mode for a schema. *

* This method is provided as an extension point for subclasses. * The default implementation ignores the {@link JavaType} parameter * and delegates to {@link #resolveRequiredMode(io.swagger.v3.oas.annotations.media.Schema)}. * * @param schema A schema annotation * @param type The JavaType of the field property that the annotation is tied to * @return The resolved required mode for the schema */ protected io.swagger.v3.oas.annotations.media.Schema.RequiredMode resolveRequiredMode( io.swagger.v3.oas.annotations.media.Schema schema, JavaType type) { return resolveRequiredMode(schema); } protected io.swagger.v3.oas.annotations.media.Schema.AccessMode resolveAccessMode(BeanPropertyDefinition propDef, JavaType type, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && !schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.AUTO)) { return schema.accessMode(); } else if (schema != null && schema.readOnly()) { return io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY; } else if (schema != null && schema.writeOnly()) { return io.swagger.v3.oas.annotations.media.Schema.AccessMode.WRITE_ONLY; } if (propDef == null) { return null; } JsonProperty.Access access = null; if (propDef instanceof POJOPropertyBuilder) { access = ((POJOPropertyBuilder) propDef).findAccess(); } boolean hasGetter = propDef.hasGetter(); boolean hasSetter = propDef.hasSetter(); boolean hasConstructorParameter = propDef.hasConstructorParameter(); boolean hasField = propDef.hasField(); if (access == null) { final BeanDescription beanDesc = _mapper.getDeserializationConfig().introspect(type); List properties = beanDesc.findProperties(); for (BeanPropertyDefinition prop : properties) { if (StringUtils.isNotBlank(prop.getInternalName()) && prop.getInternalName().equals(propDef.getInternalName())) { if (prop instanceof POJOPropertyBuilder) { access = ((POJOPropertyBuilder) prop).findAccess(); } hasGetter = hasGetter || prop.hasGetter(); hasSetter = hasSetter || prop.hasSetter(); hasConstructorParameter = hasConstructorParameter || prop.hasConstructorParameter(); hasField = hasField || prop.hasField(); break; } } } if (access == null) { if (!hasGetter && !hasField && (hasConstructorParameter || hasSetter)) { return io.swagger.v3.oas.annotations.media.Schema.AccessMode.WRITE_ONLY; } return null; } else { switch (access) { case AUTO: return io.swagger.v3.oas.annotations.media.Schema.AccessMode.AUTO; case READ_ONLY: return io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY; case READ_WRITE: return io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE; case WRITE_ONLY: return io.swagger.v3.oas.annotations.media.Schema.AccessMode.WRITE_ONLY; default: return io.swagger.v3.oas.annotations.media.Schema.AccessMode.AUTO; } } } protected Boolean resolveReadOnly(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY)) { return true; } else if (schema != null && schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.WRITE_ONLY)) { return null; } else if (schema != null && schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE)) { return null; } else if (schema != null && schema.readOnly()) { return schema.readOnly(); } return null; } protected Boolean resolveNullable(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.nullable()) { return true; } if (annotations != null) { for (Annotation annotation : annotations) { if (NULLABLE_ANNOTATIONS.contains(annotation.annotationType().getSimpleName())) { return true; } } } return null; } protected BigDecimal resolveMultipleOf(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.multipleOf() != 0) { return new BigDecimal(schema.multipleOf()); } return null; } protected Integer resolveMaxLength(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.maxLength() != Integer.MAX_VALUE && schema.maxLength() > 0) { return schema.maxLength(); } return null; } protected Integer resolveMinLength(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.minLength() > 0) { return schema.minLength(); } return null; } protected BigDecimal resolveMinimum(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && NumberUtils.isCreatable(schema.minimum())) { String filteredMinimum = schema.minimum().replace(Constants.COMMA, StringUtils.EMPTY); return new BigDecimal(filteredMinimum); } return null; } protected BigDecimal resolveMaximum(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && NumberUtils.isCreatable(schema.maximum())) { String filteredMaximum = schema.maximum().replace(Constants.COMMA, StringUtils.EMPTY); return new BigDecimal(filteredMaximum); } return null; } protected Boolean resolveExclusiveMinimum(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.exclusiveMinimum()) { return schema.exclusiveMinimum(); } return null; } protected Boolean resolveExclusiveMaximum(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.exclusiveMaximum()) { return schema.exclusiveMaximum(); } return null; } protected String resolvePattern(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.pattern())) { return schema.pattern(); } return null; } protected Integer resolveMinProperties(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.minProperties() > 0) { return schema.minProperties(); } return null; } protected Integer resolveMaxProperties(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.maxProperties() > 0) { return schema.maxProperties(); } return null; } protected List resolveRequiredProperties(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.requiredProperties() != null && schema.requiredProperties().length > 0 && StringUtils.isNotBlank(schema.requiredProperties()[0])) { return Arrays.asList(schema.requiredProperties()); } return null; } protected Boolean resolveWriteOnly(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY)) { return null; } else if (schema != null && schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.WRITE_ONLY)) { return true; } else if (schema != null && schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE)) { return null; } else if (schema != null && schema.writeOnly()) { return schema.writeOnly(); } return null; } protected ExternalDocumentation resolveExternalDocumentation(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { ExternalDocumentation external = null; if (a != null) { io.swagger.v3.oas.annotations.ExternalDocumentation externalDocumentation = a.getAnnotation(io.swagger.v3.oas.annotations.ExternalDocumentation.class); external = resolveExternalDocumentation(externalDocumentation); } if (external == null) { if (schema != null) { external = resolveExternalDocumentation(schema.externalDocs()); } } return external; } protected ExternalDocumentation resolveExternalDocumentation(io.swagger.v3.oas.annotations.ExternalDocumentation externalDocumentation) { if (externalDocumentation == null) { return null; } boolean isEmpty = true; ExternalDocumentation external = new ExternalDocumentation(); if (StringUtils.isNotBlank(externalDocumentation.description())) { isEmpty = false; external.setDescription(externalDocumentation.description()); } if (StringUtils.isNotBlank(externalDocumentation.url())) { isEmpty = false; external.setUrl(externalDocumentation.url()); } if (isEmpty) { return null; } return external; } protected Boolean resolveDeprecated(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.deprecated()) { return schema.deprecated(); } return null; } protected List resolveAllowableValues(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.allowableValues() != null && schema.allowableValues().length > 0) { return Arrays.asList(schema.allowableValues()); } return null; } protected Map resolveExtensions(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.extensions() != null && schema.extensions().length > 0) { boolean usePrefix = !openapi31; return AnnotationsUtils.getExtensions(openapi31, usePrefix, schema.extensions()); } return null; } protected void resolveDiscriminatorProperty(JavaType type, ModelConverterContext context, Schema model) { // add JsonTypeInfo.property if not member of bean JsonTypeInfo typeInfo = type.getRawClass().getDeclaredAnnotation(JsonTypeInfo.class); if (typeInfo != null) { String typeInfoProp = typeInfo.property(); if (StringUtils.isNotBlank(typeInfoProp)) { Schema modelToUpdate = model; if (StringUtils.isNotBlank(model.get$ref())) { modelToUpdate = context.getDefinedModels().get(model.get$ref().substring(SCHEMA_COMPONENT_PREFIX)); } if (modelToUpdate.getProperties() == null || !modelToUpdate.getProperties().keySet().contains(typeInfoProp)) { Schema discriminatorSchema = openapi31 ? new JsonSchema().typesItem("string").name(typeInfoProp) : new StringSchema().name(typeInfoProp); modelToUpdate.addProperties(typeInfoProp, discriminatorSchema); if (modelToUpdate.getRequired() == null || !modelToUpdate.getRequired().contains(typeInfoProp)) { modelToUpdate.addRequiredItem(typeInfoProp); } } } } } /* TODO partial implementation supporting WRAPPER_OBJECT with JsonTypeInfo.Id.CLASS and JsonTypeInfo.Id.NAME Also note that JsonTypeInfo on interfaces are not considered as multiple interfaces might have conflicting annotations, although Jackson seems to apply them if present on an interface */ protected Schema resolveWrapping(JavaType type, ModelConverterContext context, Schema model) { // add JsonTypeInfo.property if not member of bean JsonTypeInfo typeInfo = type.getRawClass().getDeclaredAnnotation(JsonTypeInfo.class); if (typeInfo != null) { JsonTypeInfo.Id id = typeInfo.use(); JsonTypeInfo.As as = typeInfo.include(); if (JsonTypeInfo.As.WRAPPER_OBJECT.equals(as)) { String name = model.getName(); if (JsonTypeInfo.Id.CLASS.equals(id)) { name = type.getRawClass().getName(); } JsonTypeName typeName = type.getRawClass().getDeclaredAnnotation((JsonTypeName.class)); if (JsonTypeInfo.Id.NAME.equals(id) && typeName != null) { name = typeName.value(); } if (JsonTypeInfo.Id.NAME.equals(id) && name == null) { name = type.getRawClass().getSimpleName(); } Schema wrapperSchema = openapi31 ? new JsonSchema().typesItem("object") : new ObjectSchema(); wrapperSchema.name(model.getName()); wrapperSchema.addProperties(name, model); return wrapperSchema; } } return model; } protected Discriminator resolveDiscriminator(JavaType type, ModelConverterContext context) { io.swagger.v3.oas.annotations.media.Schema declaredSchemaAnnotation = AnnotationsUtils.getSchemaDeclaredAnnotation(type.getRawClass()); String disc = (declaredSchemaAnnotation == null) ? "" : declaredSchemaAnnotation.discriminatorProperty(); if (disc.isEmpty()) { // longer method would involve AnnotationIntrospector.findTypeResolver(...) but: JsonTypeInfo typeInfo = type.getRawClass().getDeclaredAnnotation(JsonTypeInfo.class); if (typeInfo != null) { disc = typeInfo.property(); } } if (!disc.isEmpty()) { Discriminator discriminator = new Discriminator() .propertyName(disc); if (declaredSchemaAnnotation != null) { DiscriminatorMapping[] mappings = declaredSchemaAnnotation.discriminatorMapping(); if (mappings != null && mappings.length > 0) { for (DiscriminatorMapping mapping : mappings) { if (!mapping.value().isEmpty() && !mapping.schema().equals(Void.class)) { discriminator.mapping(mapping.value(), constructRef(context.resolve(new AnnotatedType().type(mapping.schema())).getName())); } } } } return discriminator; } return null; } protected XML resolveXml(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { // if XmlRootElement annotation, construct a Xml object and attach it to the model XmlRootElement rootAnnotation = null; XmlSchema xmlSchema = null; if (a != null) { rootAnnotation = a.getAnnotation(XmlRootElement.class); Class rawType = a.getRawType(); if (rawType != null) { Package aPackage = rawType.getPackage(); if (aPackage != null) { xmlSchema = aPackage.getAnnotation(XmlSchema.class); } } } if (rootAnnotation == null) { if (annotations != null) { for (Annotation ann : annotations) { if (ann instanceof XmlRootElement) { rootAnnotation = (XmlRootElement) ann; break; } } } } if (rootAnnotation != null && !"".equals(rootAnnotation.name()) && !JAXB_DEFAULT.equals(rootAnnotation.name())) { XML xml = new XML().name(rootAnnotation.name()); if (xmlSchema != null && isNonTrivialXmlNamespace(xmlSchema.namespace())) { xml.namespace(xmlSchema.namespace()); } // Let XmlRootElement overwrite global XmlSchema namespace if present if (isNonTrivialXmlNamespace(rootAnnotation.namespace())) { xml.namespace(rootAnnotation.namespace()); } return xml; } return null; } private boolean isNonTrivialXmlNamespace(String namespace) { return namespace != null && !"".equals(namespace) && !JAXB_DEFAULT.equals(namespace); } protected Set resolveIgnoredProperties(Annotations a, Annotation[] annotations) { Set propertiesToIgnore = new HashSet<>(); JsonIgnoreProperties ignoreProperties = a.get(JsonIgnoreProperties.class); if (ignoreProperties != null) { if (!ignoreProperties.allowGetters()) { propertiesToIgnore.addAll(Arrays.asList(ignoreProperties.value())); } } propertiesToIgnore.addAll(resolveIgnoredProperties(annotations)); return propertiesToIgnore; } protected Set resolveIgnoredProperties(Annotation[] annotations) { Set propertiesToIgnore = new HashSet<>(); if (annotations != null) { for (Annotation annotation : annotations) { if (annotation instanceof JsonIgnoreProperties) { if (!((JsonIgnoreProperties) annotation).allowGetters()) { propertiesToIgnore.addAll(Arrays.asList(((JsonIgnoreProperties) annotation).value())); break; } } } } return propertiesToIgnore; } protected Integer resolveMinItems(AnnotatedType a, io.swagger.v3.oas.annotations.media.ArraySchema arraySchema) { if (arraySchema != null) { if (arraySchema.minItems() < Integer.MAX_VALUE) { return arraySchema.minItems(); } } return null; } protected Integer resolveMaxItems(AnnotatedType a, io.swagger.v3.oas.annotations.media.ArraySchema arraySchema) { if (arraySchema != null) { if (arraySchema.maxItems() > 0) { return arraySchema.maxItems(); } } return null; } protected Boolean resolveUniqueItems(AnnotatedType a, io.swagger.v3.oas.annotations.media.ArraySchema arraySchema) { if (arraySchema != null) { if (arraySchema.uniqueItems()) { return arraySchema.uniqueItems(); } } return null; } protected Map resolveExtensions(AnnotatedType a, io.swagger.v3.oas.annotations.media.ArraySchema arraySchema) { if (arraySchema != null && arraySchema.extensions() != null && arraySchema.extensions().length > 0) { boolean usePrefix = !openapi31; return AnnotationsUtils.getExtensions(openapi31, usePrefix, arraySchema.extensions()); } return null; } protected Integer resolveMaxContains(AnnotatedType a, io.swagger.v3.oas.annotations.media.ArraySchema arraySchema) { if (arraySchema != null && arraySchema.maxContains() > 0) { return arraySchema.maxContains(); } return null; } protected Integer resolveMinContains(AnnotatedType a, io.swagger.v3.oas.annotations.media.ArraySchema arraySchema) { if (arraySchema != null && arraySchema.minContains() > 0) { return arraySchema.minContains(); } return null; } protected BigDecimal resolveExclusiveMaximumValue(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.exclusiveMaximumValue() > 0) { return new BigDecimal(schema.exclusiveMaximumValue()); } return null; } protected BigDecimal resolveExclusiveMinimumValue(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && schema.exclusiveMinimumValue() > 0) { return new BigDecimal(schema.exclusiveMinimumValue()); } return null; } protected String resolveId(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.$id())) { return schema.$id(); } return null; } protected String resolve$schema(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.$schema())) { return schema.$schema(); } return null; } protected String resolve$anchor(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.$anchor())) { return schema.$anchor(); } return null; } protected String resolve$comment(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.$comment())) { return schema.$comment(); } return null; } protected String resolve$vocabulary(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.$vocabulary())) { return schema.$vocabulary(); } return null; } protected String resolve$dynamicAnchor(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.$dynamicAnchor())) { return schema.$dynamicAnchor(); } return null; } protected String resolve$dynamicRef(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.$dynamicRef())) { return schema.$dynamicRef(); } return null; } protected String resolveContentEncoding(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.contentEncoding())) { return schema.contentEncoding(); } return null; } protected String resolveContentMediaType(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema.contentMediaType())) { return schema.contentMediaType(); } return null; } protected void resolveContains(AnnotatedType annotatedType, ArraySchema arraySchema, io.swagger.v3.oas.annotations.media.ArraySchema arraySchemaAnnotation) { final io.swagger.v3.oas.annotations.media.Schema containsAnnotation = arraySchemaAnnotation.contains(); final Schema contains = openapi31 ? new JsonSchema() : new Schema(); if (containsAnnotation.types().length > 0) { for (String type : containsAnnotation.types()) { contains.addType(type); } } arraySchema.setContains(contains); resolveSchemaMembers(contains, null, null, containsAnnotation); Integer maxContains = resolveMaxContains(annotatedType, arraySchemaAnnotation); if (maxContains != null) { arraySchema.setMaxContains(maxContains); } Integer minContains = resolveMinContains(annotatedType, arraySchemaAnnotation); if (minContains != null) { arraySchema.setMinContains(minContains); } } protected void resolveUnevaluatedItems(AnnotatedType annotatedType, ArraySchema arraySchema, io.swagger.v3.oas.annotations.media.ArraySchema arraySchemaAnnotation) { final io.swagger.v3.oas.annotations.media.Schema unevaluatedItemsAnnotation = arraySchemaAnnotation.unevaluatedItems(); final Schema unevaluatedItems = openapi31 ? new JsonSchema() : new Schema(); if (StringUtils.isNotBlank(unevaluatedItemsAnnotation.type())) { unevaluatedItems.addType(unevaluatedItemsAnnotation.type()); } if (unevaluatedItemsAnnotation.types().length > 0) { for (String type : unevaluatedItemsAnnotation.types()) { unevaluatedItems.addType(type); } } arraySchema.setUnevaluatedItems(unevaluatedItems); resolveSchemaMembers(unevaluatedItems, null, null, unevaluatedItemsAnnotation); } protected String resolveConst(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema != null && StringUtils.isNotBlank(schema._const())) { return schema._const(); } return null; } protected Map> resolveDependentRequired(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) { if (schema.dependentRequiredMap().length == 0) { return null; } final Map> dependentRequiredMap = new HashMap<>(); for (DependentRequired dependentRequired : schema.dependentRequiredMap()) { final String name = dependentRequired.name(); if (dependentRequired.value().length == 0) { continue; } final List values = Arrays.asList(dependentRequired.value()); dependentRequiredMap.put(name, values); } return dependentRequiredMap; } protected Map resolveDependentSchemas(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation, AnnotatedType annotatedType, ModelConverterContext context, Iterator next) { if (schemaAnnotation.dependentSchemas().length == 0) { return null; } final Map dependentSchemas = new HashMap<>(); for (StringToClassMapItem mapItem : schemaAnnotation.dependentSchemas()) { final String key = mapItem.key(); if (mapItem.value() == null || Void.class.equals(mapItem.value())) { continue; } final Schema schema = resolve(new AnnotatedType(mapItem.value()), context, next); if (schema == null) { continue; } dependentSchemas.put(key, schema); } return dependentSchemas; } protected Map resolvePatternProperties(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation, AnnotatedType annotatedType, ModelConverterContext context, Iterator next) { if (schemaAnnotation.patternProperties().length == 0) { return null; } final Map patternPropertyMap = new HashMap<>(); for (StringToClassMapItem patternPropertyItem : schemaAnnotation.patternProperties()) { final String key = patternPropertyItem.key(); if (Void.class.equals(patternPropertyItem.value())) { continue; } final Schema schema = resolve(new AnnotatedType(patternPropertyItem.value()), context, next); if (schema == null) { continue; } patternPropertyMap.put(key, schema); } return patternPropertyMap; } protected Map resolveProperties(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation, AnnotatedType annotatedType, ModelConverterContext context, Iterator next) { if (schemaAnnotation.properties().length == 0) { return null; } final Map propertyMap = new HashMap<>(); for (StringToClassMapItem propertyItem : schemaAnnotation.properties()) { final String key = propertyItem.key(); if (Void.class.equals(propertyItem.value())) { continue; } final Schema schema = resolve(new AnnotatedType(propertyItem.value()), context, next); if (schema == null) { continue; } propertyMap.put(key, schema); } return propertyMap; } protected void resolveSchemaMembers(Schema schema, AnnotatedType annotatedType) { resolveSchemaMembers(schema, annotatedType, null, null); } protected void resolveSchemaMembers(Schema schema, AnnotatedType annotatedType, ModelConverterContext context, Iterator next) { final JavaType type; if (annotatedType.getType() instanceof JavaType) { type = (JavaType) annotatedType.getType(); } else { type = _mapper.constructType(annotatedType.getType()); } final Annotation resolvedSchemaOrArrayAnnotation = AnnotationsUtils.mergeSchemaAnnotations(annotatedType.getCtxAnnotations(), type); final io.swagger.v3.oas.annotations.media.Schema schemaAnnotation = resolvedSchemaOrArrayAnnotation == null ? null : resolvedSchemaOrArrayAnnotation instanceof io.swagger.v3.oas.annotations.media.ArraySchema ? ((io.swagger.v3.oas.annotations.media.ArraySchema) resolvedSchemaOrArrayAnnotation).schema() : (io.swagger.v3.oas.annotations.media.Schema) resolvedSchemaOrArrayAnnotation; final BeanDescription beanDesc = _mapper.getSerializationConfig().introspect(type); Annotated a = beanDesc.getClassInfo(); Annotation[] annotations = annotatedType.getCtxAnnotations(); resolveSchemaMembers(schema, a, annotations, schemaAnnotation); if (schemaAnnotation != null) { if (schemaAnnotation.additionalProperties().equals(io.swagger.v3.oas.annotations.media.Schema.AdditionalPropertiesValue.TRUE)) { schema.additionalProperties(true); } else if (schemaAnnotation.additionalProperties().equals(io.swagger.v3.oas.annotations.media.Schema.AdditionalPropertiesValue.FALSE)) { schema.additionalProperties(false); } else { if (!schemaAnnotation.additionalPropertiesSchema().equals(Void.class)) { Schema additionalPropertiesSchema = resolve(new AnnotatedType(schemaAnnotation.additionalPropertiesSchema()), context, next); additionalPropertiesSchema = buildRefSchemaIfObject(additionalPropertiesSchema, context); schema.additionalProperties(additionalPropertiesSchema); } } } if (openapi31 && schema != null && schemaAnnotation != null) { if (!Void.class.equals(schemaAnnotation.contentSchema())) { Schema contentSchema = resolve(new AnnotatedType(schemaAnnotation.contentSchema()), context, next); contentSchema = buildRefSchemaIfObject(contentSchema, context); schema.setContentSchema(contentSchema); } if (!Void.class.equals(schemaAnnotation.propertyNames())) { Schema propertyNames = resolve(new AnnotatedType(schemaAnnotation.propertyNames()), context, next); propertyNames = buildRefSchemaIfObject(propertyNames, context); schema.setPropertyNames(propertyNames); } if (!Void.class.equals(schemaAnnotation._if())) { Schema ifSchema = resolve(new AnnotatedType(schemaAnnotation._if()), context, next); ifSchema = buildRefSchemaIfObject(ifSchema, context); schema.setIf(ifSchema); } if (!Void.class.equals(schemaAnnotation._else())) { Schema elseSchema = resolve(new AnnotatedType(schemaAnnotation._else()), context, next); elseSchema = buildRefSchemaIfObject(elseSchema, context); schema.setElse(elseSchema); } if (!Void.class.equals(schemaAnnotation.then())) { Schema thenSchema = resolve(new AnnotatedType(schemaAnnotation.then()), context, next); thenSchema = buildRefSchemaIfObject(thenSchema, context); schema.setThen(thenSchema); } if (!Void.class.equals(schemaAnnotation.unevaluatedProperties())) { Schema unevaluatedProperties = resolve(new AnnotatedType(schemaAnnotation.unevaluatedProperties()), context, next); unevaluatedProperties = buildRefSchemaIfObject(unevaluatedProperties, context); schema.setUnevaluatedProperties(unevaluatedProperties); } final Map> dependentRequired = resolveDependentRequired(a, annotations, schemaAnnotation); if (dependentRequired != null && !dependentRequired.isEmpty()) { schema.setDependentRequired(dependentRequired); } final Map dependentSchemas = resolveDependentSchemas(a, annotations, schemaAnnotation, annotatedType, context, next); if (dependentSchemas != null) { final Map processedDependentSchemas = new LinkedHashMap<>(); for (String key : dependentSchemas.keySet()) { Schema val = dependentSchemas.get(key); processedDependentSchemas.put(key, buildRefSchemaIfObject(val, context)); } if (processedDependentSchemas != null && !processedDependentSchemas.isEmpty()) { if (schema.getDependentSchemas() == null) { schema.setDependentSchemas(processedDependentSchemas); } else { schema.getDependentSchemas().putAll(processedDependentSchemas); } } } final Map patternProperties = resolvePatternProperties(a, annotations, schemaAnnotation, annotatedType, context, next); if (patternProperties != null && !patternProperties.isEmpty()) { for (String key : patternProperties.keySet()) { schema.addPatternProperty(key, buildRefSchemaIfObject(patternProperties.get(key), context)); } } final Map properties = resolveProperties(a, annotations, schemaAnnotation, annotatedType, context, next); if (properties != null && !properties.isEmpty()) { for (String key : properties.keySet()) { schema.addProperty(key, buildRefSchemaIfObject(properties.get(key), context)); } } } } protected void resolveSchemaMembers(Schema schema, Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation) { String description = resolveDescription(a, annotations, schemaAnnotation); if (StringUtils.isNotBlank(description)) { schema.description(description); } String title = resolveTitle(a, annotations, schemaAnnotation); if (StringUtils.isNotBlank(title)) { schema.title(title); } String format = resolveFormat(a, annotations, schemaAnnotation); if (StringUtils.isNotBlank(format) && StringUtils.isBlank(schema.getFormat())) { schema.format(format); } Object defaultValue = resolveDefaultValue(a, annotations, schemaAnnotation); if (defaultValue != null) { schema.setDefault(defaultValue); } else if (schemaAnnotation != null && "null".equals(schemaAnnotation.defaultValue().trim()) && schemaAnnotation.nullable()) { // Explicitly set to null when defaultValue="null" AND nullable=true schema.setDefault(null); } Object example = resolveExample(a, annotations, schemaAnnotation); if (example != null) { schema.example(example); } else if (schemaAnnotation != null && "null".equals(schemaAnnotation.example().trim()) && schemaAnnotation.nullable()) { // Explicitly set to null when example="null" AND nullable=true schema.example(null); } Boolean readOnly = resolveReadOnly(a, annotations, schemaAnnotation); if (readOnly != null) { schema.readOnly(readOnly); } Boolean nullable = resolveNullable(a, annotations, schemaAnnotation); if (nullable != null) { schema.nullable(nullable); if (openapi31 && nullable) { schema.addType("null"); } } BigDecimal multipleOf = resolveMultipleOf(a, annotations, schemaAnnotation); if (multipleOf != null) { schema.multipleOf(multipleOf); } Integer maxLength = resolveMaxLength(a, annotations, schemaAnnotation); if (maxLength != null) { schema.maxLength(maxLength); } Integer minLength = resolveMinLength(a, annotations, schemaAnnotation); if (minLength != null) { schema.minLength(minLength); } BigDecimal minimum = resolveMinimum(a, annotations, schemaAnnotation); if (minimum != null) { schema.minimum(minimum); } BigDecimal maximum = resolveMaximum(a, annotations, schemaAnnotation); if (maximum != null) { schema.maximum(maximum); } Boolean exclusiveMinimum = resolveExclusiveMinimum(a, annotations, schemaAnnotation); if (exclusiveMinimum != null) { schema.exclusiveMinimum(exclusiveMinimum); } Boolean exclusiveMaximum = resolveExclusiveMaximum(a, annotations, schemaAnnotation); if (exclusiveMaximum != null) { schema.exclusiveMaximum(exclusiveMaximum); } String pattern = resolvePattern(a, annotations, schemaAnnotation); if (StringUtils.isNotBlank(pattern)) { schema.pattern(pattern); } Integer minProperties = resolveMinProperties(a, annotations, schemaAnnotation); if (minProperties != null) { schema.minProperties(minProperties); } Integer maxProperties = resolveMaxProperties(a, annotations, schemaAnnotation); if (maxProperties != null) { schema.maxProperties(maxProperties); } List requiredProperties = resolveRequiredProperties(a, annotations, schemaAnnotation); if (requiredProperties != null) { for (String prop : requiredProperties) { addRequiredItem(schema, prop); } } Boolean writeOnly = resolveWriteOnly(a, annotations, schemaAnnotation); if (writeOnly != null) { schema.writeOnly(writeOnly); } ExternalDocumentation externalDocs = resolveExternalDocumentation(a, annotations, schemaAnnotation); if (externalDocs != null) { schema.externalDocs(externalDocs); } Boolean deprecated = resolveDeprecated(a, annotations, schemaAnnotation); if (deprecated != null) { schema.deprecated(deprecated); } List allowableValues = resolveAllowableValues(a, annotations, schemaAnnotation); if (allowableValues != null) { for (String prop : allowableValues) { schema.addEnumItemObject(prop); } } Map extensions = resolveExtensions(a, annotations, schemaAnnotation); if (extensions != null) { extensions.forEach(schema::addExtension); } if (openapi31 && schemaAnnotation != null) { if (schemaAnnotation.types().length > 0) { schema.setTypes(new LinkedHashSet<>(Arrays.asList(schemaAnnotation.types()))); } BigDecimal exclusiveMaximumValue = resolveExclusiveMaximumValue(a, annotations, schemaAnnotation); if (exclusiveMaximumValue != null) { schema.setExclusiveMaximumValue(exclusiveMaximumValue); } BigDecimal exclusiveMinimumValue = resolveExclusiveMinimumValue(a, annotations, schemaAnnotation); if (exclusiveMinimumValue != null) { schema.setExclusiveMinimumValue(exclusiveMinimumValue); } String $id = resolveId(a, annotations, schemaAnnotation); if ($id != null) { schema.set$id($id); } String $schema = resolve$schema(a, annotations, schemaAnnotation); if ($schema != null) { schema.set$schema($schema); } String $anchor = resolve$anchor(a, annotations, schemaAnnotation); if ($anchor != null) { schema.set$anchor($anchor); } String $comment = resolve$comment(a, annotations, schemaAnnotation); if ($comment != null) { schema.set$comment($comment); } String $vocabulary = resolve$vocabulary(a, annotations, schemaAnnotation); if ($vocabulary != null) { schema.set$vocabulary($vocabulary); } String $dynamicAnchor = resolve$dynamicAnchor(a, annotations, schemaAnnotation); if ($dynamicAnchor != null) { schema.$dynamicAnchor($dynamicAnchor); } String $dynamicRef = resolve$dynamicRef(a, annotations, schemaAnnotation); if ($dynamicRef != null) { schema.$dynamicRef($dynamicRef); } String contentEncoding = resolveContentEncoding(a, annotations, schemaAnnotation); if (contentEncoding != null) { schema.setContentEncoding(contentEncoding); } String contentMediaType = resolveContentMediaType(a, annotations, schemaAnnotation); if (contentMediaType != null) { schema.setContentMediaType(contentMediaType); } if (schemaAnnotation.examples().length > 0) { List parsedExamples = io.swagger.v3.core.util.AnnotationsUtils.parseExamplesArray(schemaAnnotation); if (schema.getExamples() == null || schema.getExamples().isEmpty()) { schema.setExamples(parsedExamples); } else { schema.getExamples().addAll(parsedExamples); } } String _const = resolveConst(a, annotations, schemaAnnotation); if (_const != null) { schema.setConst(_const); } } } protected void addRequiredItem(Schema model, String propName) { updateRequiredItem(model, propName); } protected boolean updateRequiredItem(Schema model, String propName) { if (model == null || propName == null || StringUtils.isBlank(propName)) { return false; } if (model.getRequired() == null || model.getRequired().isEmpty()) { model.addRequiredItem(propName); return true; } if (model.getRequired().stream().noneMatch(propName::equals)) { model.addRequiredItem(propName); return true; } return false; } protected boolean shouldIgnoreClass(Type type) { if (type instanceof Class) { Class cls = (Class) type; if (cls.getName().equals("javax.ws.rs.Response")) { return true; } } else { if (type instanceof com.fasterxml.jackson.core.type.ResolvedType) { com.fasterxml.jackson.core.type.ResolvedType rt = (com.fasterxml.jackson.core.type.ResolvedType) type; LOGGER.trace("Can't check class {}, {}", type, rt.getRawClass().getName()); if (rt.getRawClass().equals(Class.class)) { return true; } } } return false; } private List getIgnoredProperties(BeanDescription beanDescription) { AnnotationIntrospector introspector = _mapper.getSerializationConfig().getAnnotationIntrospector(); JsonIgnoreProperties.Value v = introspector.findPropertyIgnorals(beanDescription.getClassInfo()); Set ignored = null; if (v != null) { ignored = v.findIgnoredForSerialization(); } return ignored == null ? Collections.emptyList() : new ArrayList<>(ignored); } /** * Decorate the name based on the JsonView */ protected String decorateModelName(AnnotatedType type, String originalName) { if (StringUtils.isBlank(originalName)) { return originalName; } String name = originalName; if (type.getJsonViewAnnotation() != null && type.getJsonViewAnnotation().value().length > 0) { String COMBINER = "-or-"; StringBuilder sb = new StringBuilder(); for (Class view : type.getJsonViewAnnotation().value()) { sb.append(view.getSimpleName()).append(COMBINER); } String suffix = sb.substring(0, sb.length() - COMBINER.length()); name = originalName + "_" + suffix; } return name; } protected boolean hiddenByJsonView(Annotation[] annotations, AnnotatedType type) { JsonView jsonView = type.getJsonViewAnnotation(); if (jsonView == null) { return false; } Class[] filters = jsonView.value(); boolean containsJsonViewAnnotation = !type.isIncludePropertiesWithoutJSONView(); for (Annotation ant : annotations) { if (ant instanceof JsonView) { containsJsonViewAnnotation = true; Class[] views = ((JsonView) ant).value(); for (Class f : filters) { for (Class v : views) { if (v == f || v.isAssignableFrom(f)) { return false; } } } } } return containsJsonViewAnnotation; } private void resolveArraySchema(AnnotatedType annotatedType, ArraySchema schema, io.swagger.v3.oas.annotations.media.ArraySchema resolvedArrayAnnotation) { Integer minItems = resolveMinItems(annotatedType, resolvedArrayAnnotation); if (minItems != null) { schema.minItems(minItems); } Integer maxItems = resolveMaxItems(annotatedType, resolvedArrayAnnotation); if (maxItems != null) { schema.maxItems(maxItems); } Boolean uniqueItems = resolveUniqueItems(annotatedType, resolvedArrayAnnotation); if (uniqueItems != null) { schema.uniqueItems(uniqueItems); } Map extensions = resolveExtensions(annotatedType, resolvedArrayAnnotation); if (extensions != null) { schema.extensions(extensions); } if (resolvedArrayAnnotation != null) { if (AnnotationsUtils.hasSchemaAnnotation(resolvedArrayAnnotation.arraySchema())) { resolveSchemaMembers(schema, null, null, resolvedArrayAnnotation.arraySchema()); } if (openapi31) { if (AnnotationsUtils.hasSchemaAnnotation(resolvedArrayAnnotation.contains())) { resolveContains(annotatedType, schema, resolvedArrayAnnotation); } if (AnnotationsUtils.hasSchemaAnnotation(resolvedArrayAnnotation.unevaluatedItems())) { resolveUnevaluatedItems(annotatedType, schema, resolvedArrayAnnotation); } if (resolvedArrayAnnotation.prefixItems().length > 0) { for (io.swagger.v3.oas.annotations.media.Schema prefixItemAnnotation : resolvedArrayAnnotation.prefixItems()) { final Schema prefixItem = new JsonSchema(); if (StringUtils.isNotBlank(prefixItemAnnotation.type())) { prefixItem.addType(prefixItemAnnotation.type()); } resolveSchemaMembers(prefixItem, null, null, prefixItemAnnotation); schema.addPrefixItem(prefixItem); } } // TODO `ArraySchema.items` is deprecated, when removed, remove this block if (schema.getItems() != null && AnnotationsUtils.hasSchemaAnnotation(resolvedArrayAnnotation.items())) { for (String type : resolvedArrayAnnotation.items().types()) { schema.getItems().addType(type); } } if (schema.getItems() != null && AnnotationsUtils.hasSchemaAnnotation(resolvedArrayAnnotation.schema())) { for (String type : resolvedArrayAnnotation.schema().types()) { schema.getItems().addType(type); } } } } } public ModelResolver openapi31(boolean openapi31) { this.openapi31 = openapi31; return this; } public boolean isOpenapi31() { return openapi31; } public void setOpenapi31(boolean openapi31) { this.openapi31 = openapi31; } public ModelResolver configuration(Configuration configuration) { this.setConfiguration(configuration); return this; } public Configuration getConfiguration() { return configuration; } public void setConfiguration(Configuration configuration) { this.configuration = configuration; if (configuration != null) { if (configuration.isOpenAPI31() != null) { this.openapi31(configuration.isOpenAPI31()); } if (configuration.getSchemaResolution() != null) { this.schemaResolution(configuration.getSchemaResolution()); } // see if we have a processor if (StringUtils.isNotBlank(configuration.getValidatorProcessorClass())) { try { Class processorClass = getClass().getClassLoader().loadClass(configuration.getValidatorProcessorClass()); if (ValidatorProcessor.class.isAssignableFrom(processorClass)) { validatorProcessor = (ValidatorProcessor) processorClass.newInstance(); } } catch (Exception e) { LOGGER.error("Unable to load validator processor class: " + configuration.getValidatorProcessorClass(), e); } } } } protected boolean isObjectSchema(Schema schema) { return SchemaTypeUtils.isObjectSchema(schema); } protected boolean isInferredObjectSchema(Schema schema) { return ((schema.getProperties() != null && !schema.getProperties().isEmpty()) || (schema.getPatternProperties() != null && !schema.getPatternProperties().isEmpty()) || (schema.getAdditionalProperties() != null) || (schema.getUnevaluatedProperties() != null) || (schema.getRequired() != null && !schema.getRequired().isEmpty()) || (schema.getPropertyNames() != null) || (schema.getDependentRequired() != null && !schema.getDependentRequired().isEmpty()) || (schema.getDependentSchemas() != null && !schema.getDependentSchemas().isEmpty()) || (schema.getMinProperties() != null && schema.getMinProperties() > 0) || (schema.getMaxProperties() != null && schema.getMaxProperties() > 0)); } protected boolean isArraySchema(Schema schema) { return SchemaTypeUtils.isArraySchema(schema); } protected boolean isStringSchema(Schema schema) { return SchemaTypeUtils.isStringSchema(schema); } protected boolean isNumberSchema(Schema schema) { return SchemaTypeUtils.isNumberSchema(schema); } private AnnotatedMember invokeMethod(final BeanDescription beanDesc, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Method m = BeanDescription.class.getMethod(methodName); return (AnnotatedMember) m.invoke(beanDesc); } protected Schema buildRefSchemaIfObject(Schema schema, ModelConverterContext context) { if (schema == null) { return null; } Schema result = schema; if (isObjectSchema(schema) && StringUtils.isNotBlank(schema.getName())) { if (context.getDefinedModels().containsKey(schema.getName())) { result = openapi31 ? new JsonSchema() : new Schema(); result.$ref(constructRef(schema.getName())); } } return result; } protected boolean applySchemaResolution() { return !openapi31 || (Boolean.parseBoolean(System.getProperty(Schema.APPLY_SCHEMA_RESOLUTION_PROPERTY, "false")) || Boolean.parseBoolean(System.getenv(Schema.APPLY_SCHEMA_RESOLUTION_PROPERTY))); } private Optional resolveArraySchemaWithCycleGuard( io.swagger.v3.oas.annotations.media.ArraySchema ctxArraySchema, AnnotatedType annotatedType, boolean openapi31, Schema property) { boolean processSchemaImplementation = !typesBeingResolved.contains(annotatedType); Optional reResolvedProperty; if (processSchemaImplementation) { typesBeingResolved.add(annotatedType); } try { reResolvedProperty = AnnotationsUtils.getArraySchema(ctxArraySchema, annotatedType.getComponents(), null, openapi31, property, processSchemaImplementation ); } finally { if (processSchemaImplementation) { typesBeingResolved.remove(annotatedType); } } return reResolvedProperty; } /** * Checks if the given JavaType represents a java.util.stream.Stream */ private boolean isStreamType(JavaType type) { return type != null && type.getRawClass() != null && java.util.stream.Stream.class.isAssignableFrom(type.getRawClass()); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/PackageVersion.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.Versioned; import com.fasterxml.jackson.core.util.VersionUtil; public final class PackageVersion implements Versioned { public static final Version VERSION = VersionUtil.parseVersion( "0.5.1-SNAPSHOT", "io.swagger", "swagger-core"); @Override public Version version() { return VERSION; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/PathsSerializer.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import java.io.IOException; import java.util.Map.Entry; public class PathsSerializer extends JsonSerializer { @Override public void serialize( Paths value, JsonGenerator jgen, SerializerProvider provider) throws IOException { if (value != null && value.getExtensions() != null && !value.getExtensions().isEmpty()) { jgen.writeStartObject(); if (!value.isEmpty()) { for (Entry entry: value.entrySet()) { jgen.writeObjectField(entry.getKey() , entry.getValue()); } } for (Entry entry: value.getExtensions().entrySet()) { jgen.writeObjectField(entry.getKey() , entry.getValue()); } jgen.writeEndObject(); } else { provider.defaultSerializeValue(value, jgen); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/Schema31Serializer.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.ResolvableSerializer; import io.swagger.v3.oas.models.media.Schema; import java.io.IOException; public class Schema31Serializer extends JsonSerializer implements ResolvableSerializer { private JsonSerializer defaultSerializer; public Schema31Serializer(JsonSerializer serializer) { defaultSerializer = serializer; } @Override public void resolve(SerializerProvider serializerProvider) throws JsonMappingException { if (defaultSerializer instanceof ResolvableSerializer) { ((ResolvableSerializer) defaultSerializer).resolve(serializerProvider); } } @Override public void serialize( Schema value, JsonGenerator jgen, SerializerProvider provider) throws IOException { if (value.getBooleanSchemaValue() != null) { jgen.writeBoolean(value.getBooleanSchemaValue()); return; } boolean hasNullExample = value.getExampleSetFlag() && value.getExample() == null; boolean hasNullDefault = value.getDefaultSetFlag() && value.getDefault() == null; if (hasNullExample || hasNullDefault) { jgen.writeStartObject(); defaultSerializer.unwrappingSerializer(null).serialize(value, jgen, provider); if (hasNullExample) { jgen.writeNullField("example"); } if (hasNullDefault) { jgen.writeNullField("default"); } jgen.writeEndObject(); } else { defaultSerializer.serialize(value, jgen, provider); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/SchemaSerializer.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.ResolvableSerializer; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import java.io.IOException; public class SchemaSerializer extends JsonSerializer implements ResolvableSerializer { private JsonSerializer defaultSerializer; public SchemaSerializer(JsonSerializer serializer) { defaultSerializer = serializer; } @Override public void resolve(SerializerProvider serializerProvider) throws JsonMappingException { if (defaultSerializer instanceof ResolvableSerializer) { ((ResolvableSerializer) defaultSerializer).resolve(serializerProvider); } } @Override public void serialize( Schema value, JsonGenerator jgen, SerializerProvider provider) throws IOException { if (StringUtils.isBlank(value.get$ref())) { boolean hasNullExample = value.getExampleSetFlag() && value.getExample() == null; boolean hasNullDefault = value.getDefaultSetFlag() && value.getDefault() == null; if (hasNullExample || hasNullDefault) { jgen.writeStartObject(); defaultSerializer.unwrappingSerializer(null).serialize(value, jgen, provider); if (hasNullExample) { jgen.writeNullField("example"); } if (hasNullDefault) { jgen.writeNullField("default"); } jgen.writeEndObject(); } else { defaultSerializer.serialize(value, jgen, provider); } } else { // handle ref schema serialization skipping all other props jgen.writeStartObject(); jgen.writeStringField("$ref", value.get$ref()); jgen.writeEndObject(); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/SwaggerAnnotationIntrospector.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.jsontype.NamedType; import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class SwaggerAnnotationIntrospector extends AnnotationIntrospector { private static final long serialVersionUID = 1L; @Override public Version version() { return PackageVersion.VERSION; } @Override public Boolean hasRequiredMarker(AnnotatedMember m) { XmlElement elem = m.getAnnotation(XmlElement.class); if (elem != null) { if (elem.required()) { return true; } } JsonProperty jsonProperty = m.getAnnotation(JsonProperty.class); if (jsonProperty != null) { if (jsonProperty.required()) { return true; } } Schema ann = m.getAnnotation(Schema.class); if (ann != null) { if (ann.required()) { return ann.required(); } } ArraySchema arraySchema = m.getAnnotation(ArraySchema.class); if (arraySchema != null) { if (arraySchema.arraySchema().required()) { return arraySchema.arraySchema().required(); } if (arraySchema.schema().required()) { return arraySchema.schema().required(); } } return null; } @Override public String findPropertyDescription(Annotated a) { Schema model = a.getAnnotation(Schema.class); if (model != null && !"".equals(model.description())) { return model.description(); } return null; } @Override public List findSubtypes(Annotated a) { Schema schema = a.getAnnotation(Schema.class); if (schema == null) { final ArraySchema arraySchema = a.getAnnotation(ArraySchema.class); if (arraySchema != null) { schema = arraySchema.schema(); } } if (AnnotationsUtils.hasSchemaAnnotation(schema)) { final Class[] classes = schema.subTypes(); final List names = new ArrayList<>(classes.length); for (Class subType : classes) { names.add(new NamedType(subType)); } if (!names.isEmpty()) { return names; } } return Collections.emptyList(); } @Override public String findTypeName(AnnotatedClass ac) { io.swagger.v3.oas.annotations.media.Schema mp = AnnotationsUtils.getSchemaAnnotation(ac); // allow override of name from annotation if (mp != null && !mp.name().isEmpty()) { return mp.name(); } return null; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/SwaggerModule.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.databind.module.SimpleModule; public class SwaggerModule extends SimpleModule { private static final long serialVersionUID = 1L; public SwaggerModule() { super(PackageVersion.VERSION); } @Override public void setupModule(SetupContext context) { super.setupModule(context); context.insertAnnotationIntrospector(new SwaggerAnnotationIntrospector()); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/TypeNameResolver.java ================================================ package io.swagger.v3.core.jackson; import com.fasterxml.jackson.databind.JavaType; import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.core.util.PrimitiveType; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.text.WordUtils; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.Set; /** * Helper class used for converting well-known (property) types into * Swagger type names. */ public class TypeNameResolver { public static final TypeNameResolver std = new TypeNameResolver(); private boolean useFqn=false; protected TypeNameResolver() { } public boolean getUseFqn() { return this.useFqn; } public void setUseFqn(boolean useFqn) { this.useFqn = useFqn; } public String nameForType(JavaType type, Options... options) { return nameForType(type, options.length == 0 ? Collections.emptySet() : EnumSet.copyOf(Arrays.asList(options))); } public String nameForType(JavaType type, Set options) { if (type.hasGenericTypes()) { return nameForGenericType(type, options); } final String name = findStdName(type); return (name == null) ? nameForClass(type, options) : name; } protected String nameForClass(JavaType type, Set options) { return nameForClass(type.getRawClass(), options); } protected String nameForClass(Class cls, Set options) { if (options.contains(Options.SKIP_API_MODEL)) { return getNameOfClass(cls); } io.swagger.v3.oas.annotations.media.Schema mp = AnnotationsUtils.getSchemaDeclaredAnnotation(cls); final String modelName = mp == null ? null : StringUtils.trimToNull(mp.name()); return modelName == null ? getNameOfClass(cls) : modelName; } protected String getNameOfClass(Class cls) { return useFqn ? cls.getName().replace("$", ".") : cls.getSimpleName(); } protected String nameForGenericType(JavaType type, Set options) { final StringBuilder generic = new StringBuilder(nameForClass(type, options)); final int count = type.containedTypeCount(); for (int i = 0; i < count; ++i) { final JavaType arg = type.containedType(i); final String argName = PrimitiveType.fromType(arg) != null ? nameForClass(arg, options) : nameForType(arg, options); generic.append(WordUtils.capitalize(argName)); } return generic.toString(); } protected String findStdName(JavaType type) { return PrimitiveType.getCommonName(type); } public enum Options { SKIP_API_MODEL; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/Components31Mixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.swagger.v3.core.jackson.CallbackSerializer; import io.swagger.v3.oas.models.callbacks.Callback; import java.util.Map; public abstract class Components31Mixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonSerialize(contentUsing = CallbackSerializer.class) public abstract Map getCallbacks(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/ComponentsMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.swagger.v3.core.jackson.CallbackSerializer; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.callbacks.Callback; import java.util.Map; public abstract class ComponentsMixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonSerialize(contentUsing = CallbackSerializer.class) public abstract Map getCallbacks(); @JsonIgnore public abstract Map getPathItems(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/DateSchemaMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import java.util.Map; public abstract class DateSchemaMixin { @JsonFormat (shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") public abstract Object getExample(); @JsonFormat (shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") public abstract Object getDefault(); @JsonFormat (shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") public abstract Object getEnum(); @JsonIgnore public abstract Object getJsonSchemaImpl(); @JsonIgnore public abstract Map getJsonSchema(); @JsonIgnore public abstract Boolean getBooleanSchemaValue(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/Discriminator31Mixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import java.util.Map; public abstract class Discriminator31Mixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/DiscriminatorMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonIgnore; import java.util.Map; public abstract class DiscriminatorMixin { @JsonIgnore public abstract Map getExtensions(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/ExampleMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import java.util.Map; public abstract class ExampleMixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonInclude(value = JsonInclude.Include.NON_NULL, content = JsonInclude.Include.ALWAYS) public abstract Object getValue(); @JsonIgnore public abstract boolean getValueSetFlag(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/ExtensionsMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import java.util.Map; public abstract class ExtensionsMixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/Info31Mixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import java.util.Map; public abstract class Info31Mixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/InfoMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import java.util.Map; public abstract class InfoMixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonIgnore public abstract String getSummary(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/LicenseMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import java.util.Map; public abstract class LicenseMixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonIgnore public abstract String getIdentifier(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/MediaTypeMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import java.util.Map; public abstract class MediaTypeMixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonIgnore public abstract boolean getExampleSetFlag(); @JsonInclude(value = JsonInclude.Include.NON_NULL, content = JsonInclude.Include.ALWAYS) public abstract Object getExample(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/OpenAPI31Mixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.swagger.v3.core.jackson.PathsSerializer; import io.swagger.v3.oas.models.Paths; import java.util.Map; public abstract class OpenAPI31Mixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonSerialize(using = PathsSerializer.class) public abstract Paths getPaths(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/OpenAPIMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.swagger.v3.core.jackson.PathsSerializer; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import java.util.Map; public abstract class OpenAPIMixin { @JsonAnyGetter @JsonInclude public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonSerialize(using = PathsSerializer.class) public abstract Paths getPaths(); @JsonIgnore public abstract Map getWebhooks(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/OperationMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.swagger.v3.core.jackson.ApiResponsesSerializer; import io.swagger.v3.core.jackson.CallbackSerializer; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.responses.ApiResponses; import java.util.Map; public abstract class OperationMixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonSerialize(contentUsing = CallbackSerializer.class) public abstract Map getCallbacks(); @JsonSerialize(using = ApiResponsesSerializer.class) public abstract ApiResponses getResponses(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/Schema31Mixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.io.IOException; import java.math.BigDecimal; import java.util.Map; import java.util.Set; @JsonPropertyOrder(value = {"type", "format", "if", "then", "else"}, alphabetic = true) public abstract class Schema31Mixin { @JsonIgnore public abstract Map getJsonSchema(); @JsonIgnore public abstract Boolean getNullable(); @JsonIgnore public abstract Boolean getExclusiveMinimum(); @JsonIgnore public abstract Boolean getExclusiveMaximum(); @JsonProperty("exclusiveMinimum") public abstract BigDecimal getExclusiveMinimumValue(); @JsonProperty("exclusiveMaximum") public abstract BigDecimal getExclusiveMaximumValue(); @JsonIgnore public abstract String getType(); @JsonProperty("type") @JsonSerialize(using = TypeSerializer.class) public abstract Set getTypes(); @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonIgnore public abstract boolean getExampleSetFlag(); @JsonInclude(value = JsonInclude.Include.NON_NULL, content = JsonInclude.Include.ALWAYS) public abstract Object getExample(); @JsonIgnore public abstract Object getJsonSchemaImpl(); @JsonIgnore public abstract Boolean getBooleanSchemaValue(); public static class TypeSerializer extends JsonSerializer> { @Override public void serialize(Set types, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { if (types != null && types.size() == 1) { jsonGenerator.writeString((String)types.toArray()[0]); } else if (types != null && types.size() > 1){ jsonGenerator.writeStartArray(); for (String t: types) { jsonGenerator.writeString(t); } jsonGenerator.writeEndArray(); } } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/SchemaConverterMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.v3.oas.models.media.Schema; import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.Set; public abstract class SchemaConverterMixin { @JsonIgnore public abstract Map getJsonSchema(); @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonIgnore public abstract boolean getExampleSetFlag(); @JsonInclude(value = JsonInclude.Include.NON_NULL, content = JsonInclude.Include.ALWAYS) public abstract Object getExample(); @JsonIgnore public abstract Object getJsonSchemaImpl(); @JsonIgnore public abstract BigDecimal getExclusiveMinimumValue(); @JsonIgnore public abstract BigDecimal getExclusiveMaximumValue(); @JsonIgnore public abstract Schema getContains(); @JsonIgnore public abstract String get$id(); @JsonIgnore public abstract String get$anchor(); @JsonIgnore public abstract String get$schema(); @JsonIgnore public abstract Set getTypes(); @JsonIgnore public abstract Map getPatternProperties(); @JsonIgnore public abstract List getPrefixItems(); @JsonIgnore public abstract String getContentEncoding(); @JsonIgnore public abstract String getContentMediaType(); @JsonIgnore public abstract Schema getContentSchema(); @JsonIgnore public abstract Schema getPropertyNames(); @JsonIgnore public abstract Object getUnevaluatedProperties(); @JsonIgnore public abstract Integer getMaxContains(); @JsonIgnore public abstract Integer getMinContains(); @JsonIgnore public abstract Schema getAdditionalItems(); @JsonIgnore public abstract Schema getUnevaluatedItems(); @JsonIgnore public abstract Schema getIf(); @JsonIgnore public abstract Schema getElse(); @JsonIgnore public abstract Schema getThen(); @JsonIgnore public abstract Map getDependentSchemas(); @JsonIgnore public abstract Map> getDependentRequired(); @JsonIgnore public abstract String get$comment(); @JsonIgnore public abstract List getExamples(); @JsonIgnore public abstract Object getConst(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/mixin/SchemaMixin.java ================================================ package io.swagger.v3.core.jackson.mixin; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.v3.oas.models.media.Schema; import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.Set; public abstract class SchemaMixin { @JsonAnyGetter public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonIgnore public abstract boolean getExampleSetFlag(); @JsonInclude(value = JsonInclude.Include.NON_NULL, content = JsonInclude.Include.ALWAYS) public abstract Object getExample(); @JsonIgnore public abstract Map getJsonSchema(); @JsonIgnore public abstract BigDecimal getExclusiveMinimumValue(); @JsonIgnore public abstract BigDecimal getExclusiveMaximumValue(); @JsonIgnore public abstract Schema getContains(); @JsonIgnore public abstract String get$id(); @JsonIgnore public abstract String get$anchor(); @JsonIgnore public abstract String get$schema(); @JsonIgnore public abstract Set getTypes(); @JsonIgnore public abstract Map getPatternProperties(); @JsonIgnore public abstract Object getJsonSchemaImpl(); @JsonIgnore public abstract List getPrefixItems(); @JsonIgnore public abstract String getContentEncoding(); @JsonIgnore public abstract String getContentMediaType(); @JsonIgnore public abstract Schema getContentSchema(); @JsonIgnore public abstract Schema getPropertyNames(); @JsonIgnore public abstract Object getUnevaluatedProperties(); @JsonIgnore public abstract Integer getMaxContains(); @JsonIgnore public abstract Integer getMinContains(); @JsonIgnore public abstract Schema getAdditionalItems(); @JsonIgnore public abstract Schema getUnevaluatedItems(); @JsonIgnore public abstract Schema getIf(); @JsonIgnore public abstract Schema getElse(); @JsonIgnore public abstract Schema getThen(); @JsonIgnore public abstract Map getDependentSchemas(); @JsonIgnore public abstract Map> getDependentRequired(); @JsonIgnore public abstract String get$comment(); @JsonIgnore public abstract List getExamples(); @JsonIgnore public abstract Object getConst(); @JsonIgnore public abstract Boolean getBooleanSchemaValue(); } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/model/ApiDescription.java ================================================ package io.swagger.v3.core.model; public class ApiDescription { private String path; private String method; public ApiDescription(String path, String method) { this.setPath(path); this.setMethod(method); } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.Annotated; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.media.DependentRequired; import io.swagger.v3.oas.annotations.media.DependentSchema; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.SchemaProperty; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.ExternalDocumentation; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.Encoding; import io.swagger.v3.oas.models.media.JsonSchema; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.oas.models.servers.ServerVariable; import io.swagger.v3.oas.models.servers.ServerVariables; import io.swagger.v3.oas.models.tags.Tag; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import static io.swagger.v3.oas.annotations.media.Schema.DEFAULT_SENTINEL; public abstract class AnnotationsUtils { private static Logger LOGGER = LoggerFactory.getLogger(AnnotationsUtils.class); public static final String COMPONENTS_REF = Components.COMPONENTS_SCHEMAS_REF; public static boolean hasSchemaAnnotation(io.swagger.v3.oas.annotations.media.Schema schema) { if (schema == null) { return false; } if (StringUtils.isBlank(schema.type()) && StringUtils.isBlank(schema.format()) && StringUtils.isBlank(schema.title()) && StringUtils.isBlank(schema.description()) && StringUtils.isBlank(schema.ref()) && StringUtils.isBlank(schema.name()) && schema.multipleOf() == 0 && StringUtils.isBlank(schema.maximum()) && StringUtils.isBlank(schema.minimum()) && !schema.exclusiveMinimum() && !schema.exclusiveMaximum() && schema.maxLength() == Integer.MAX_VALUE && schema.minLength() == 0 && schema.minProperties() == 0 && schema.maxProperties() == 0 && schema.requiredProperties().length == 0 && !schema.required() && schema.requiredMode().equals(io.swagger.v3.oas.annotations.media.Schema.RequiredMode.AUTO) && !schema.nullable() && !schema.readOnly() && !schema.writeOnly() && schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.AUTO) && !schema.deprecated() && schema.allowableValues().length == 0 && DEFAULT_SENTINEL.equals(schema.defaultValue()) && schema.implementation().equals(Void.class) && StringUtils.isBlank(schema.example()) && StringUtils.isBlank(schema.pattern()) && schema.not().equals(Void.class) && schema.allOf().length == 0 && schema.oneOf().length == 0 && schema.anyOf().length == 0 && schema.subTypes().length == 0 && !getExternalDocumentation(schema.externalDocs()).isPresent() && StringUtils.isBlank(schema.discriminatorProperty()) && schema.discriminatorMapping().length == 0 && schema.extensions().length == 0 && !schema.hidden() && !schema.enumAsRef() && schema.dependentSchemas().length == 0 && schema.patternProperties().length == 0 && schema.unevaluatedProperties().equals(Void.class) && schema.types().length == 0 && schema.exclusiveMinimumValue() == 0 && schema.exclusiveMaximumValue() == 0 && StringUtils.isBlank(schema.$id()) && StringUtils.isBlank(schema.$schema()) && StringUtils.isBlank(schema.$anchor()) && StringUtils.isBlank(schema.contentEncoding()) && StringUtils.isBlank(schema.contentMediaType()) && schema.contentSchema().equals(Void.class) && schema.propertyNames().equals(Void.class) && schema._if().equals(Void.class) && schema._else().equals(Void.class) && schema.then().equals(Void.class) && StringUtils.isBlank(schema.$comment()) && schema.dependentRequiredMap().length == 0 && schema.patternProperties().length == 0 && schema.properties().length == 0 && StringUtils.isBlank(schema._const()) && schema.additionalProperties().equals(io.swagger.v3.oas.annotations.media.Schema.AdditionalPropertiesValue.USE_ADDITIONAL_PROPERTIES_ANNOTATION) && schema.additionalPropertiesSchema().equals(Void.class) ) { return false; } return true; } public static boolean equals(Annotation thisAnnotation, Annotation thatAnnotation) { if (thisAnnotation == null && thatAnnotation == null) { return true; } else if (thisAnnotation == null || thatAnnotation == null) { return false; } if (!thisAnnotation.annotationType().equals(thatAnnotation.annotationType())) { return false; } if (thisAnnotation instanceof io.swagger.v3.oas.annotations.media.Schema) { return equals((io.swagger.v3.oas.annotations.media.Schema) thisAnnotation, (io.swagger.v3.oas.annotations.media.Schema) thatAnnotation); } else if (thisAnnotation instanceof io.swagger.v3.oas.annotations.media.ArraySchema) { return equals((io.swagger.v3.oas.annotations.media.ArraySchema)thisAnnotation, (io.swagger.v3.oas.annotations.media.ArraySchema)thatAnnotation); } return true; } public static boolean equals(io.swagger.v3.oas.annotations.media.ArraySchema thisArraySchema, io.swagger.v3.oas.annotations.media.ArraySchema thatArraySchema) { if (thisArraySchema == null && thatArraySchema == null) { return true; } else if (thisArraySchema == null || thatArraySchema == null) { return false; } if (thisArraySchema.maxItems() != thatArraySchema.maxItems()) { return false; } if (thisArraySchema.minItems() != thatArraySchema.minItems()) { return false; } if (thisArraySchema.uniqueItems() != thatArraySchema.uniqueItems()) { return false; } if (!Arrays.equals(thisArraySchema.extensions(), thatArraySchema.extensions())) { return false; } if (!equals(thisArraySchema.schema(), thatArraySchema.schema())) { return false; } if (!equals(thisArraySchema.contains(), thatArraySchema.contains())) { return false; } if (thisArraySchema.maxContains() != thatArraySchema.maxContains()) { return false; } if (thisArraySchema.minContains() != thatArraySchema.minContains()) { return false; } if (!Arrays.equals(thisArraySchema.prefixItems(), thatArraySchema.prefixItems())) { return false; } return true; } public static boolean equals(io.swagger.v3.oas.annotations.media.Schema thisSchema, io.swagger.v3.oas.annotations.media.Schema thatSchema) { if (thisSchema == null && thatSchema == null) { return true; } else if (thisSchema == null || thatSchema == null) { return false; } if (!StringUtils.equals(thisSchema.type(), thatSchema.type())) { return false; } if (!StringUtils.equals(thisSchema.format(), thatSchema.format())) { return false; } if (!StringUtils.equals(thisSchema.title(), thatSchema.title())) { return false; } if (!StringUtils.equals(thisSchema.description(), thatSchema.description())) { return false; } if (!StringUtils.equals(thisSchema.ref(), thatSchema.ref())) { return false; } if (!StringUtils.equals(thisSchema.name(), thatSchema.name())) { return false; } if (!StringUtils.equals(thisSchema.defaultValue(), thatSchema.defaultValue())) { return false; } if (!StringUtils.equals(thisSchema.maximum(), thatSchema.maximum())) { return false; } if (!StringUtils.equals(thisSchema.minimum(), thatSchema.minimum())) { return false; } if (!StringUtils.equals(thisSchema.example(), thatSchema.example())) { return false; } if (!StringUtils.equals(thisSchema.pattern(), thatSchema.pattern())) { return false; } if (!StringUtils.equals(thisSchema.discriminatorProperty(), thatSchema.discriminatorProperty())) { return false; } if (thisSchema.multipleOf() != thatSchema.multipleOf()) { return false; } if (thisSchema.minLength() != thatSchema.minLength()) { return false; } if (thisSchema.minProperties() != thatSchema.minProperties()) { return false; } if (thisSchema.maxProperties() != thatSchema.maxProperties()) { return false; } if (thisSchema.maxLength() != thatSchema.maxLength()) { return false; } if (!Arrays.equals(thisSchema.allOf(), thatSchema.allOf())) { return false; } if (!Arrays.equals(thisSchema.oneOf(), thatSchema.oneOf())) { return false; } if (!Arrays.equals(thisSchema.anyOf(), thatSchema.anyOf())) { return false; } if (!Arrays.equals(thisSchema.subTypes(), thatSchema.subTypes())) { return false; } if (!Arrays.equals(thisSchema.discriminatorMapping(), thatSchema.discriminatorMapping())) { return false; } if (!Arrays.equals(thisSchema.extensions(), thatSchema.extensions())) { return false; } if (!Arrays.equals(thisSchema.allowableValues(), thatSchema.allowableValues())) { return false; } if (!Arrays.equals(thisSchema.requiredProperties(), thatSchema.requiredProperties())) { return false; } if (thisSchema.exclusiveMinimum() != thatSchema.exclusiveMinimum()) { return false; } if (thisSchema.exclusiveMaximum() != thatSchema.exclusiveMaximum()) { return false; } if (thisSchema.required() != thatSchema.required()) { return false; } if (!thisSchema.requiredMode().equals(thatSchema.requiredMode())) { return false; } if (thisSchema.nullable() != thatSchema.nullable()) { return false; } if (thisSchema.readOnly() != thatSchema.readOnly()) { return false; } if (thisSchema.writeOnly() != thatSchema.writeOnly()) { return false; } if (!thisSchema.accessMode().equals(thatSchema.accessMode())) { return false; } if (thisSchema.deprecated() != thatSchema.deprecated()) { return false; } if (thisSchema.hidden() != thatSchema.hidden()) { return false; } if (thisSchema.enumAsRef() != thatSchema.enumAsRef()) { return false; } if (!thisSchema.implementation().equals(thatSchema.implementation())) { return false; } if (!thisSchema.not().equals(thatSchema.not())) { return false; } if (!StringUtils.equals(thisSchema.externalDocs().description(), thatSchema.externalDocs().description())) { return false; } if (!StringUtils.equals(thisSchema.externalDocs().url(), thatSchema.externalDocs().url())) { return false; } if (thisSchema.externalDocs().extensions().length != thatSchema.externalDocs().extensions().length) { return false; } if (!Arrays.equals(thisSchema.extensions(), thatSchema.extensions())) { return false; } if (!thisSchema.additionalProperties().equals(thatSchema.additionalProperties())) { return false; } if (!Arrays.equals(thisSchema.types(), thatSchema.types())) { return false; } if (thisSchema.exclusiveMaximumValue() != thatSchema.exclusiveMaximumValue()) { return false; } if (thisSchema.exclusiveMinimumValue() != thatSchema.exclusiveMinimumValue()) { return false; } if (!StringUtils.equals(thisSchema.$id(), thatSchema.$id())) { return false; } if (!StringUtils.equals(thisSchema.$schema(), thatSchema.$schema())) { return false; } if (!StringUtils.equals(thisSchema.$anchor(), thatSchema.$anchor())) { return false; } if (!StringUtils.equals(thisSchema.contentEncoding(), thatSchema.contentEncoding())) { return false; } if (!StringUtils.equals(thisSchema.contentMediaType(), thatSchema.contentMediaType())) { return false; } if (!StringUtils.equals(thisSchema.contentMediaType(), thatSchema.contentMediaType())) { return false; } if (!thisSchema.contentSchema().equals(thatSchema.contentSchema())) { return false; } if (!thisSchema.propertyNames().equals(thatSchema.propertyNames())) { return false; } if (!thisSchema._if().equals(thatSchema._if())) { return false; } if (!thisSchema._else().equals(thatSchema._else())) { return false; } if (!thisSchema.then().equals(thatSchema.then())) { return false; } if (!thisSchema.$comment().equals(thatSchema.$comment())) { return false; } if (!thisSchema._const().equals(thatSchema._const())) { return false; } return true; } public static boolean hasArrayAnnotation(io.swagger.v3.oas.annotations.media.ArraySchema array) { if (array == null) { return false; } if (!array.uniqueItems() && array.maxItems() == Integer.MIN_VALUE && array.minItems() == Integer.MAX_VALUE && !hasSchemaAnnotation(array.schema()) && !hasSchemaAnnotation(array.arraySchema()) && !hasSchemaAnnotation(array.contains()) && array.maxContains() == 0 && array.minContains() == 0 && !hasSchemaAnnotation(array.unevaluatedItems()) && array.prefixItems().length == 0 ) { return false; } return true; } public static Optional getExample(ExampleObject example) { return getExample(example, false); } public static Optional getExample(ExampleObject example, boolean ignoreName) { if (example == null) { return Optional.empty(); } Example exampleObject = new Example(); if (!ignoreName && StringUtils.isNotBlank(example.name())) { if (StringUtils.isNotBlank(example.name())) { exampleObject.setDescription(example.name()); } resolveExample(exampleObject, example); return Optional.of(exampleObject); } else if (ignoreName){ if (resolveExample(exampleObject, example)) { return Optional.of(exampleObject); } } return Optional.empty(); } private static boolean resolveExample(Example exampleObject, ExampleObject example) { boolean isEmpty = true; if (StringUtils.isNotBlank(example.summary())) { isEmpty = false; exampleObject.setSummary(example.summary()); } if (StringUtils.isNotBlank(example.description())) { isEmpty = false; exampleObject.setDescription(example.description()); } if (StringUtils.isNotBlank(example.externalValue())) { isEmpty = false; exampleObject.setExternalValue(example.externalValue()); } if (StringUtils.isNotBlank(example.value())) { isEmpty = false; try { ObjectMapper mapper = ObjectMapperFactory.buildStrictGenericObjectMapper(); exampleObject.setValue(mapper.readTree(example.value())); } catch (IOException e) { exampleObject.setValue(example.value()); } } if (StringUtils.isNotBlank(example.ref())) { isEmpty = false; exampleObject.set$ref(example.ref()); } if (example.extensions().length > 0) { isEmpty = false; Map extensions = AnnotationsUtils.getExtensions(example.extensions()); if (extensions != null) { extensions.forEach(exampleObject::addExtension); } } return !isEmpty; } public static Optional getArraySchema(io.swagger.v3.oas.annotations.media.ArraySchema arraySchema, JsonView jsonViewAnnotation) { return getArraySchema(arraySchema, null, jsonViewAnnotation); } public static Optional getArraySchema(io.swagger.v3.oas.annotations.media.ArraySchema arraySchema, Components components, JsonView jsonViewAnnotation) { return getArraySchema(arraySchema, components, jsonViewAnnotation, false); } public static Optional getArraySchema(io.swagger.v3.oas.annotations.media.ArraySchema arraySchema, Components components, JsonView jsonViewAnnotation, boolean openapi31) { Optional result = getArraySchema(arraySchema, components, jsonViewAnnotation, openapi31, null); if (result.isPresent()) { return Optional.of((ArraySchema) result.get()); } return Optional.empty(); } public static Optional getArraySchema(io.swagger.v3.oas.annotations.media.ArraySchema arraySchema, Components components, JsonView jsonViewAnnotation, boolean openapi31, Schema existingSchema) { return getArraySchema(arraySchema, components, jsonViewAnnotation, openapi31, existingSchema, false); } public static Optional getArraySchema(io.swagger.v3.oas.annotations.media.ArraySchema arraySchema, Components components, JsonView jsonViewAnnotation, boolean openapi31, Schema existingSchema, boolean processSchemaImplementation) { if (arraySchema == null || !hasArrayAnnotation(arraySchema)) { if (existingSchema == null) { return Optional.empty(); } else { return Optional.of(existingSchema); } } Schema arraySchemaObject = null; if (!openapi31) { if (existingSchema != null && existingSchema instanceof ArraySchema) { return Optional.of((ArraySchema) existingSchema); } arraySchemaObject = new ArraySchema(); } else { if (existingSchema == null) { arraySchemaObject = new JsonSchema().typesItem("array"); } else { arraySchemaObject = existingSchema; } } if (arraySchema.uniqueItems()) { arraySchemaObject.setUniqueItems(arraySchema.uniqueItems()); } if (arraySchema.maxItems() > 0) { arraySchemaObject.setMaxItems(arraySchema.maxItems()); } if (arraySchema.minItems() < Integer.MAX_VALUE) { arraySchemaObject.setMinItems(arraySchema.minItems()); } getSchemaFromAnnotation(arraySchema.contains(), components, jsonViewAnnotation, openapi31).ifPresent(arraySchemaObject::setContains); getSchemaFromAnnotation(arraySchema.unevaluatedItems(), components, jsonViewAnnotation, openapi31).ifPresent(arraySchemaObject::setUnevaluatedItems); if (arraySchema.maxContains() > 0) { arraySchemaObject.setMaxContains(arraySchema.maxContains()); } if (arraySchema.minContains() > 0) { arraySchemaObject.setMinContains(arraySchema.minContains()); } if (arraySchema.prefixItems().length > 0) { for (io.swagger.v3.oas.annotations.media.Schema prefixItem : arraySchema.prefixItems()) { getSchemaFromAnnotation(prefixItem, components, jsonViewAnnotation, openapi31).ifPresent(arraySchemaObject::addPrefixItem); } } if (arraySchema.extensions().length > 0) { boolean usePrefix = !openapi31; Map extensions = AnnotationsUtils.getExtensions(openapi31, usePrefix, arraySchema.extensions()); if (extensions != null) { extensions.forEach(arraySchemaObject::addExtension); } } if (arraySchema.schema() != null) { if (arraySchema.schema().implementation().equals(Void.class)) { getSchemaFromAnnotation(arraySchema.schema(), components, jsonViewAnnotation, openapi31, arraySchemaObject.getItems()) .ifPresent(arraySchemaObject::setItems); } else if (processSchemaImplementation) { getSchema(arraySchema.schema(), arraySchema, false, arraySchema.schema().implementation(), components, jsonViewAnnotation, openapi31) .ifPresent(arraySchemaObject::setItems); } } if (arraySchema.arraySchema() != null) { applyArraySchemaAnnotation(arraySchema.arraySchema(), arraySchemaObject, openapi31); } return Optional.of(arraySchemaObject); } private static void applyArraySchemaAnnotation(io.swagger.v3.oas.annotations.media.Schema arraySchemaAnnotation, Schema arraySchemaObject, boolean openapi31) { if (StringUtils.isNotBlank(arraySchemaAnnotation.description())) { arraySchemaObject.setDescription(arraySchemaAnnotation.description()); } if (StringUtils.isNotBlank(arraySchemaAnnotation.title())) { arraySchemaObject.setTitle(arraySchemaAnnotation.title()); } if (arraySchemaAnnotation.deprecated()) { arraySchemaObject.deprecated(true); } if (arraySchemaAnnotation.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY)) { arraySchemaObject.setReadOnly(true); arraySchemaObject.setWriteOnly(null); } else if (arraySchemaAnnotation.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.WRITE_ONLY)) { arraySchemaObject.setReadOnly(null); arraySchemaObject.setWriteOnly(true); } else if (arraySchemaAnnotation.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE)) { arraySchemaObject.setReadOnly(null); arraySchemaObject.setWriteOnly(null); } if (openapi31 && arraySchemaAnnotation.examples().length > 0) { arraySchemaObject.setExamples(parseExamplesArray(arraySchemaAnnotation)); } } public static Optional getSchemaFromAnnotation(io.swagger.v3.oas.annotations.media.Schema schema, JsonView jsonViewAnnotation) { return getSchemaFromAnnotation(schema, jsonViewAnnotation, false); } public static Optional getSchemaFromAnnotation(io.swagger.v3.oas.annotations.media.Schema schema, JsonView jsonViewAnnotation, boolean openapi31) { return getSchemaFromAnnotation(schema, null, jsonViewAnnotation, openapi31); } public static Optional getSchemaFromAnnotation(io.swagger.v3.oas.annotations.media.Schema schema, Components components, JsonView jsonViewAnnotation) { return getSchemaFromAnnotation(schema, components, jsonViewAnnotation, false); } public static Optional getSchemaFromAnnotation(io.swagger.v3.oas.annotations.media.Schema schema, Components components, JsonView jsonViewAnnotation, boolean openapi31) { return getSchemaFromAnnotation(schema, components, jsonViewAnnotation, openapi31, null); } public static Optional getSchemaFromAnnotation( io.swagger.v3.oas.annotations.media.Schema schema, Components components, JsonView jsonViewAnnotation, boolean openapi31, Schema existingSchema) { return getSchemaFromAnnotation(schema, components, jsonViewAnnotation, openapi31, existingSchema, null); } public static Optional getSchemaFromAnnotation( io.swagger.v3.oas.annotations.media.Schema schema, Components components, JsonView jsonViewAnnotation, boolean openapi31, Schema existingSchema, ModelConverterContext context) { return getSchemaFromAnnotation(schema, components, jsonViewAnnotation, openapi31, existingSchema, Schema.SchemaResolution.DEFAULT, null); } public static Optional getSchemaFromAnnotation( io.swagger.v3.oas.annotations.media.Schema schema, Components components, JsonView jsonViewAnnotation, boolean openapi31, Schema existingSchema, Schema.SchemaResolution schemaResolution, ModelConverterContext context) { if (schema == null || !hasSchemaAnnotation(schema)) { if (existingSchema == null || (!openapi31 && Schema.SchemaResolution.DEFAULT.equals(schemaResolution))) { return Optional.empty(); } else if (existingSchema != null && (openapi31 || Schema.SchemaResolution.INLINE.equals(schemaResolution))) { return Optional.of(existingSchema); } } Schema schemaObject = null; if (!openapi31) { if (existingSchema != null) { if (!Schema.SchemaResolution.DEFAULT.equals(schemaResolution)) { schemaObject = existingSchema; } else { return Optional.of(existingSchema); } } if (Schema.SchemaResolution.DEFAULT.equals(schemaResolution)) { if (schema != null && (schema.oneOf().length > 0 || schema.allOf().length > 0 || schema.anyOf().length > 0)) { schemaObject = new ComposedSchema(); } else { schemaObject = new Schema(); } } else if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution)) { if (existingSchema == null) { schemaObject = new Schema(); } else { schemaObject = existingSchema; } } } else { if (existingSchema == null) { schemaObject = new JsonSchema(); } else { schemaObject = existingSchema; } } if (schema == null) { return Optional.of(schemaObject); } if (StringUtils.isNotBlank(schema.description())) { schemaObject.setDescription(schema.description()); } if (StringUtils.isNotBlank(schema.ref())) { schemaObject.set$ref(schema.ref()); } if (StringUtils.isNotBlank(schema.type())) { schemaObject.setType(schema.type()); } if (schema.types().length > 0) { schemaObject.setTypes(new LinkedHashSet<>(Arrays.asList(schema.types()))); } if (StringUtils.isNotBlank(schema.$id())) { schemaObject.set$id(schema.$id()); } if (StringUtils.isNotBlank(schema.$schema())) { schemaObject.set$schema(schema.$schema()); } if (StringUtils.isNotBlank(schema.$anchor())) { schemaObject.set$anchor(schema.$anchor()); } if (StringUtils.isNotBlank(schema.$vocabulary())) { schemaObject.set$vocabulary(schema.$vocabulary()); } if (StringUtils.isNotBlank(schema.$dynamicAnchor())) { schemaObject.set$dynamicAnchor(schema.$dynamicAnchor()); } if (StringUtils.isNotBlank(schema.$dynamicRef())) { schemaObject.set$dynamicRef(schema.$dynamicRef()); } if (StringUtils.isNotBlank(schema.contentEncoding())) { schemaObject.setContentEncoding(schema.contentEncoding()); } if (StringUtils.isNotBlank(schema.contentMediaType())) { schemaObject.setContentMediaType(schema.contentMediaType()); } if (schema.exclusiveMaximumValue() != Integer.MAX_VALUE && schema.exclusiveMaximumValue() > 0) { schemaObject.setExclusiveMaximumValue(BigDecimal.valueOf(schema.exclusiveMaximumValue())); } if (schema.exclusiveMinimumValue() > 0) { schemaObject.setExclusiveMinimumValue(BigDecimal.valueOf(schema.exclusiveMinimumValue())); } if (!schema.contentSchema().equals(Void.class)) { schemaObject.setContentSchema(resolveSchemaFromType(schema.contentSchema(), components, jsonViewAnnotation, openapi31, null, null, context)); } if (!schema.propertyNames().equals(Void.class)) { schemaObject.setPropertyNames(resolveSchemaFromType(schema.propertyNames(), components, jsonViewAnnotation, openapi31, null, null, context)); } if (!schema._if().equals(Void.class)) { schemaObject.setIf(resolveSchemaFromType(schema._if(), components, jsonViewAnnotation, openapi31, null, null, context)); } if (!schema._else().equals(Void.class)) { schemaObject.setElse(resolveSchemaFromType(schema._else(), components, jsonViewAnnotation, openapi31, null, null, context)); } if (!schema.then().equals(Void.class)) { schemaObject.setThen(resolveSchemaFromType(schema.then(), components, jsonViewAnnotation, openapi31, null, null, context)); } if (StringUtils.isNotBlank(schema._const())) { try { Object _const; if (openapi31) { _const = Json31.mapper().readTree(schema._const()); } else { _const = Json.mapper().readTree(schema._const()); } schemaObject.setConst(_const); } catch (IOException e) { schemaObject.setConst(schema._const()); } } if (StringUtils.isNotBlank(schema.$comment())) { schemaObject.set$comment(schema.$comment()); } if (schema.dependentRequiredMap().length > 0) { final Map> dependentRequired = new LinkedHashMap<>(); for (DependentRequired dependentRequiredAnnotation : schema.dependentRequiredMap()) { dependentRequired.put(dependentRequiredAnnotation.name(), Arrays.asList(dependentRequiredAnnotation.value())); } schemaObject.setDependentRequired(dependentRequired); } if (schema.dependentSchemas().length > 0) { final Map dependentSchema = new LinkedHashMap<>(); for (StringToClassMapItem mapItem : schema.dependentSchemas()) { dependentSchema.put(mapItem.key(), resolveSchemaFromType(mapItem.value(), components, jsonViewAnnotation, openapi31, null, null, context)); } schemaObject.setDependentSchemas(dependentSchema); } if (schema.patternProperties().length > 0) { final Map patternProperties = new LinkedHashMap<>(); for (StringToClassMapItem mapItem : schema.patternProperties()) { patternProperties.put(mapItem.key(), resolveSchemaFromType(mapItem.value(), components, jsonViewAnnotation, openapi31, null, null, context)); } schemaObject.setPatternProperties(patternProperties); } if (schema.properties().length > 0) { final Map properties = new LinkedHashMap<>(); for (StringToClassMapItem mapItem : schema.properties()) { properties.put(mapItem.key(), resolveSchemaFromType(mapItem.value(), components, jsonViewAnnotation, openapi31, null, null, context)); } schemaObject.setProperties(properties); } if (!schema.unevaluatedProperties().equals(Void.class)) { schemaObject.setUnevaluatedProperties(resolveSchemaFromType(schema.unevaluatedProperties(), components, jsonViewAnnotation, openapi31, null, null, context)); } if (openapi31 && schema.examples().length > 0) { schemaObject.setExamples(parseExamplesArray(schema)); } if (!DEFAULT_SENTINEL.equals(schema.defaultValue())){ setDefaultSchema(schema, openapi31, schemaObject); } if (StringUtils.isNotBlank(schema.example()) && (!openapi31 || schema.examples().length == 0)) { setExampleSchema(schema, openapi31, schemaObject); } if (StringUtils.isNotBlank(schema.format())) { schemaObject.setFormat(schema.format()); } if (StringUtils.isNotBlank(schema.pattern())) { schemaObject.setPattern(schema.pattern()); } if (schema.readOnly()) { schemaObject.setReadOnly(schema.readOnly()); } if (schema.deprecated()) { schemaObject.setDeprecated(schema.deprecated()); } if (schema.exclusiveMaximum()) { schemaObject.setExclusiveMaximum(schema.exclusiveMaximum()); } if (schema.exclusiveMinimum()) { schemaObject.setExclusiveMinimum(schema.exclusiveMinimum()); } if (schema.maxProperties() > 0) { schemaObject.setMaxProperties(schema.maxProperties()); } if (schema.maxLength() != Integer.MAX_VALUE && schema.maxLength() > 0) { schemaObject.setMaxLength(schema.maxLength()); } if (schema.minProperties() > 0) { schemaObject.setMinProperties(schema.minProperties()); } if (schema.minLength() > 0) { schemaObject.setMinLength(schema.minLength()); } if (schema.multipleOf() != 0) { schemaObject.setMultipleOf(BigDecimal.valueOf(schema.multipleOf())); } if (NumberUtils.isCreatable(schema.maximum())) { String filteredMaximum = schema.maximum().replace(Constants.COMMA, StringUtils.EMPTY); schemaObject.setMaximum(new BigDecimal(filteredMaximum)); } if (NumberUtils.isCreatable(schema.minimum())) { String filteredMinimum = schema.minimum().replace(Constants.COMMA, StringUtils.EMPTY); schemaObject.setMinimum(new BigDecimal(filteredMinimum)); } if (schema.nullable()) { if (openapi31) { schemaObject.addType("null"); } else { schemaObject.setNullable(true); } } if (StringUtils.isNotBlank(schema.title())) { schemaObject.setTitle(schema.title()); } if (schema.writeOnly()) { schemaObject.setWriteOnly(schema.writeOnly()); } // process after readOnly and writeOnly if (schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY)) { schemaObject.setReadOnly(true); schemaObject.setWriteOnly(null); } else if (schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.WRITE_ONLY)) { schemaObject.setReadOnly(null); schemaObject.setWriteOnly(true); } else if (schema.accessMode().equals(io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE)) { schemaObject.setReadOnly(null); schemaObject.setWriteOnly(null); } if (schema.requiredProperties().length > 0) { schemaObject.setRequired(Arrays.asList(schema.requiredProperties())); } if (schema.allowableValues().length > 0) { schemaObject.setEnum(Arrays.asList(schema.allowableValues())); } if (schema.extensions().length > 0) { boolean usePrefix = !openapi31; Map extensions = AnnotationsUtils.getExtensions(openapi31, usePrefix, schema.extensions()); if (extensions != null) { extensions.forEach(schemaObject::addExtension); } } getExternalDocumentation(schema.externalDocs(), openapi31).ifPresent(schemaObject::setExternalDocs); if (!schema.not().equals(Void.class)) { Class schemaImplementation = schema.not(); Schema notSchemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, null, null, context); schemaObject.setNot(notSchemaObject); } if (schema.oneOf().length > 0) { Class[] schemaImplementations = schema.oneOf(); for (Class schemaImplementation : schemaImplementations) { Schema oneOfSchemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, null, null, context); schemaObject.addOneOfItem(oneOfSchemaObject); } } if (schema.anyOf().length > 0) { Class[] schemaImplementations = schema.anyOf(); for (Class schemaImplementation : schemaImplementations) { Schema anyOfSchemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, null, null, context); schemaObject.addAnyOfItem(anyOfSchemaObject); } } if (schema.allOf().length > 0) { Class[] schemaImplementations = schema.allOf(); for (Class schemaImplementation : schemaImplementations) { Schema allOfSchemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, null, null, context); schemaObject.addAllOfItem(allOfSchemaObject); } } if (schema.additionalProperties().equals(io.swagger.v3.oas.annotations.media.Schema.AdditionalPropertiesValue.TRUE)) { schemaObject.additionalProperties(true); } else if (schema.additionalProperties().equals(io.swagger.v3.oas.annotations.media.Schema.AdditionalPropertiesValue.FALSE)) { schemaObject.additionalProperties(false); } else { if (!schema.additionalPropertiesSchema().equals(Void.class)) { schemaObject.additionalProperties(resolveSchemaFromType(schema.additionalPropertiesSchema(), components, jsonViewAnnotation, openapi31, null, null, context)); } } return Optional.of(schemaObject); } private static void setExampleSchema(io.swagger.v3.oas.annotations.media.Schema schema, boolean openapi31, Schema schemaObject) { String exampleValue = schema.example().trim(); final ObjectMapper mapper = openapi31 ? Json31.mapper() : Json.mapper(); try { JsonNode node = mapper.readTree(exampleValue); // Only parse "null" as null value when nullable=true if (node.isNull() && schema.nullable()) { schemaObject.setExample(null); } else if (node.isObject() || node.isArray()) { schemaObject.setExample(node); } else { schemaObject.setExample(exampleValue); } } catch (IOException ignored) { schemaObject.setExample(exampleValue); } } private static void setDefaultSchema(io.swagger.v3.oas.annotations.media.Schema schema, boolean openapi31, Schema schemaObject) { String defaultValue = schema.defaultValue().trim(); final ObjectMapper mapper = openapi31 ? Json31.mapper() : Json.mapper(); try { JsonNode node = mapper.readTree(defaultValue); // Only parse "null" as null value when nullable=true if (node.isNull() && schema.nullable()) { schemaObject.setDefault(null); } else if (node.isObject() || node.isArray()) { schemaObject.setDefault(node); } else { schemaObject.setDefault(defaultValue); } } catch (IOException ignored) { schemaObject.setDefault(defaultValue); } } public static List parseExamplesArray(io.swagger.v3.oas.annotations.media.Schema schema) { String[] examplesArray = schema.examples(); List parsedExamples = new ArrayList<>(); final ObjectMapper mapper = Json31.mapper(); for (String exampleStr : examplesArray) { if (StringUtils.isBlank(exampleStr)) { parsedExamples.add(exampleStr); continue; } String trimmed = exampleStr.trim(); try { JsonNode node = mapper.readTree(trimmed); // Only parse "null" as null value when nullable=true if (node.isNull() && schema.nullable()) { parsedExamples.add(null); } else if (node.isObject() || node.isArray()) { parsedExamples.add(node); } else { parsedExamples.add(trimmed); } } catch (IOException ignored) { parsedExamples.add(trimmed); } } return parsedExamples; } public static Schema resolveSchemaFromType(Class schemaImplementation, Components components, JsonView jsonViewAnnotation) { return resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, false); } public static Schema resolveSchemaFromType(Class schemaImplementation, Components components, JsonView jsonViewAnnotation, boolean openapi31) { return resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, null, null, null); } public static Schema resolveSchemaFromType(Class schemaImplementation, Components components, JsonView jsonViewAnnotation, boolean openapi31, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation, io.swagger.v3.oas.annotations.media.ArraySchema arrayAnnotation, ModelConverterContext context) { Schema schemaObject; PrimitiveType primitiveType = PrimitiveType.fromType(schemaImplementation); if (primitiveType != null) { schemaObject = openapi31 ? primitiveType.createProperty31() : primitiveType.createProperty(); } else { schemaObject = new Schema(); ResolvedSchema resolvedSchema = null; if (context == null) { resolvedSchema = ModelConverters.getInstance(openapi31).readAllAsResolvedSchema(new AnnotatedType().type(schemaImplementation).components(components).jsonViewAnnotation(jsonViewAnnotation)); } else { Schema resSchema = context.resolve(new AnnotatedType().type(schemaImplementation).components(components).jsonViewAnnotation(jsonViewAnnotation)); if (resSchema != null) { resolvedSchema = new ResolvedSchema(); resolvedSchema.schema = resSchema; resolvedSchema.referencedSchemas = context.getDefinedModels(); } } Map schemaMap; if (resolvedSchema != null) { schemaMap = resolvedSchema.referencedSchemas; if (schemaMap != null) { schemaMap.forEach((key, referencedSchema) -> { if (components != null) { if (context != null) { context.defineModel(key, referencedSchema); } components.addSchemas(key, referencedSchema); } }); } if (resolvedSchema.schema != null) { if (StringUtils.isNotBlank(resolvedSchema.schema.getName())) { schemaObject.set$ref(COMPONENTS_REF + resolvedSchema.schema.getName()); } else { schemaObject = resolvedSchema.schema; } } } } // Schema existingSchemaObject = clone(schemaObject, openapi31); Schema existingSchemaObject = schemaObject; if (openapi31) { Optional reResolvedSchema = resolveSiblings(existingSchemaObject, components, jsonViewAnnotation, openapi31, schemaAnnotation, arrayAnnotation); if (reResolvedSchema.isPresent()) { existingSchemaObject = reResolvedSchema.get(); } } if (StringUtils.isBlank(existingSchemaObject.get$ref()) && StringUtils.isBlank(existingSchemaObject.getType())) { // default to string existingSchemaObject.setType("string"); } return existingSchemaObject; } private static Optional resolveSiblings(Schema existingSchemaObject, Components components, JsonView jsonViewAnnotation, boolean openapi31, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation, io.swagger.v3.oas.annotations.media.ArraySchema arrayAnnotation) { Optional reResolvedSchema; reResolvedSchema = getSchemaFromAnnotation(schemaAnnotation, components, jsonViewAnnotation, openapi31, existingSchemaObject); // Return the reResolvedSchema if the schemaAnnotation has incurred differences if (reResolvedSchema.isPresent() && !reResolvedSchema.get().equals(existingSchemaObject)) { return reResolvedSchema; } // If there were no changes based upon the schemaAnnotation, check the arrayAnnotation's schema if (arrayAnnotation != null && arrayAnnotation.schema() != null) { reResolvedSchema = getSchemaFromAnnotation(arrayAnnotation.schema(), components, jsonViewAnnotation, openapi31, existingSchemaObject); if (reResolvedSchema.isPresent()) { return reResolvedSchema; } } // If neither of the schema annotations applied any changes, check the arrayAnnotation return getArraySchema(arrayAnnotation, components, null, openapi31, existingSchemaObject); } public static Optional> getTags(io.swagger.v3.oas.annotations.tags.Tag[] tags, boolean skipOnlyName) { if (tags == null) { return Optional.empty(); } Set tagsList = new LinkedHashSet<>(); for (io.swagger.v3.oas.annotations.tags.Tag tag : tags) { if (StringUtils.isBlank(tag.name())) { continue; } if (skipOnlyName && StringUtils.isBlank(tag.description()) && StringUtils.isBlank(tag.externalDocs().description()) && StringUtils.isBlank(tag.externalDocs().url())) { continue; } Tag tagObject = new Tag(); if (StringUtils.isNotBlank(tag.description())) { tagObject.setDescription(tag.description()); } tagObject.setName(tag.name()); getExternalDocumentation(tag.externalDocs()).ifPresent(tagObject::setExternalDocs); if (tag.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(tag.extensions()); if (extensions != null) { extensions.forEach(tagObject::addExtension); } } tagsList.add(tagObject); } if (tagsList.isEmpty()) { return Optional.empty(); } return Optional.of(tagsList); } public static Optional> getServers(io.swagger.v3.oas.annotations.servers.Server[] servers) { if (servers == null) { return Optional.empty(); } List serverObjects = new ArrayList<>(); for (io.swagger.v3.oas.annotations.servers.Server server : servers) { getServer(server).ifPresent(serverObjects::add); } if (serverObjects.isEmpty()) { return Optional.empty(); } return Optional.of(serverObjects); } public static Optional getServer(io.swagger.v3.oas.annotations.servers.Server server) { if (server == null) { return Optional.empty(); } Server serverObject = new Server(); boolean isEmpty = true; if (StringUtils.isNotBlank(server.url())) { serverObject.setUrl(server.url()); isEmpty = false; } if (StringUtils.isNotBlank(server.description())) { serverObject.setDescription(server.description()); isEmpty = false; } if (server.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(server.extensions()); if (extensions != null) { extensions.forEach(serverObject::addExtension); } isEmpty = false; } if (isEmpty) { return Optional.empty(); } io.swagger.v3.oas.annotations.servers.ServerVariable[] serverVariables = server.variables(); if (serverVariables.length > 0) { ServerVariables serverVariablesObject = new ServerVariables(); for (io.swagger.v3.oas.annotations.servers.ServerVariable serverVariable : serverVariables) { ServerVariable serverVariableObject = new ServerVariable(); if (StringUtils.isNotBlank(serverVariable.description())) { serverVariableObject.setDescription(serverVariable.description()); } if (StringUtils.isNotBlank(serverVariable.defaultValue())) { serverVariableObject.setDefault(serverVariable.defaultValue()); } if (serverVariable.allowableValues() != null && serverVariable.allowableValues().length > 0) { if (StringUtils.isNotBlank(serverVariable.allowableValues()[0])) { serverVariableObject.setEnum(Arrays.asList(serverVariable.allowableValues())); } } if (serverVariable.extensions() != null && serverVariable.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(serverVariable.extensions()); if (extensions != null) { extensions.forEach(serverVariableObject::addExtension); } } serverVariablesObject.addServerVariable(serverVariable.name(), serverVariableObject); } serverObject.setVariables(serverVariablesObject); } return Optional.of(serverObject); } public static Optional getExternalDocumentation(io.swagger.v3.oas.annotations.ExternalDocumentation externalDocumentation) { return getExternalDocumentation(externalDocumentation, false); } public static Optional getExternalDocumentation(io.swagger.v3.oas.annotations.ExternalDocumentation externalDocumentation, boolean openapi31) { if (externalDocumentation == null) { return Optional.empty(); } boolean isEmpty = true; ExternalDocumentation external = new ExternalDocumentation(); if (StringUtils.isNotBlank(externalDocumentation.description())) { isEmpty = false; external.setDescription(externalDocumentation.description()); } if (StringUtils.isNotBlank(externalDocumentation.url())) { isEmpty = false; external.setUrl(externalDocumentation.url()); } if (externalDocumentation.extensions() != null && externalDocumentation.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, externalDocumentation.extensions()); if (extensions != null) { if (openapi31) { extensions.forEach(external::addExtension31); } else { extensions.forEach(external::addExtension); } isEmpty = false; } } if (isEmpty) { return Optional.empty(); } return Optional.of(external); } public static Optional getInfo(io.swagger.v3.oas.annotations.info.Info info) { return getInfo(info, false); } public static Optional getInfo(io.swagger.v3.oas.annotations.info.Info info, boolean openapi31) { if (info == null) { return Optional.empty(); } boolean isEmpty = true; Info infoObject = new Info(); if (StringUtils.isNotBlank(info.description())) { infoObject.setDescription(info.description()); isEmpty = false; } if (StringUtils.isNotBlank(info.termsOfService())) { infoObject.setTermsOfService(info.termsOfService()); isEmpty = false; } if (StringUtils.isNotBlank(info.title())) { infoObject.setTitle(info.title()); isEmpty = false; } if (StringUtils.isNotBlank(info.version())) { infoObject.setVersion(info.version()); isEmpty = false; } if (StringUtils.isNotBlank(info.summary())) { infoObject.setSummary(info.summary()); isEmpty = false; } if (info.extensions() != null && info.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, info.extensions()); if (extensions != null) { if (openapi31) { extensions.forEach(infoObject::addExtension31); } else { extensions.forEach(infoObject::addExtension); } isEmpty = false; } } if (isEmpty) { return Optional.empty(); } getContact(info.contact()).ifPresent(infoObject::setContact); getLicense(info.license()).ifPresent(infoObject::setLicense); return Optional.of(infoObject); } public static Optional getContact(io.swagger.v3.oas.annotations.info.Contact contact) { return getContact(contact, false); } public static Optional getContact(io.swagger.v3.oas.annotations.info.Contact contact, boolean openapi31) { if (contact == null) { return Optional.empty(); } boolean isEmpty = true; Contact contactObject = new Contact(); if (StringUtils.isNotBlank(contact.email())) { contactObject.setEmail(contact.email()); isEmpty = false; } if (StringUtils.isNotBlank(contact.name())) { contactObject.setName(contact.name()); isEmpty = false; } if (StringUtils.isNotBlank(contact.url())) { contactObject.setUrl(contact.url()); isEmpty = false; } if (contact.extensions() != null && contact.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, contact.extensions()); if (extensions != null) { if(openapi31) { extensions.forEach(contactObject::addExtension31); } else { extensions.forEach(contactObject::addExtension); } isEmpty = false; } } if (isEmpty) { return Optional.empty(); } return Optional.of(contactObject); } public static Optional getLicense(io.swagger.v3.oas.annotations.info.License license) { return getLicense(license, false); } public static Optional getLicense(io.swagger.v3.oas.annotations.info.License license, boolean openapi31) { if (license == null) { return Optional.empty(); } License licenseObject = new License(); boolean isEmpty = true; if (StringUtils.isNotBlank(license.name())) { licenseObject.setName(license.name()); isEmpty = false; } if (StringUtils.isNotBlank(license.url())) { licenseObject.setUrl(license.url()); isEmpty = false; } if (StringUtils.isNotBlank(license.identifier())) { licenseObject.setIdentifier(license.identifier()); isEmpty = false; } if (license.extensions() != null && license.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, license.extensions()); if (extensions != null) { if (openapi31) { extensions.forEach(licenseObject::addExtension31); } else { extensions.forEach(licenseObject::addExtension); } isEmpty = false; } } if (isEmpty) { return Optional.empty(); } return Optional.of(licenseObject); } public static Map getLinks(io.swagger.v3.oas.annotations.links.Link[] links) { return getLinks(links, false); } public static Map getLinks(io.swagger.v3.oas.annotations.links.Link[] links, boolean openapi31) { Map linkMap = new HashMap<>(); if (links == null) { return linkMap; } for (io.swagger.v3.oas.annotations.links.Link link : links) { getLink(link, openapi31).ifPresent(linkResult -> linkMap.put(link.name(), linkResult)); } return linkMap; } public static Optional getLink(io.swagger.v3.oas.annotations.links.Link link) { return getLink(link, false); } public static Optional getLink(io.swagger.v3.oas.annotations.links.Link link, boolean openapi31) { if (link == null) { return Optional.empty(); } boolean isEmpty = true; Link linkObject = new Link(); if (StringUtils.isNotBlank(link.description())) { linkObject.setDescription(link.description()); isEmpty = false; } if (StringUtils.isNotBlank(link.operationId())) { linkObject.setOperationId(link.operationId()); isEmpty = false; if (StringUtils.isNotBlank(link.operationRef())) { LOGGER.debug("OperationId and OperatonRef are mutually exclusive, there must be only one setted"); } } else { if (StringUtils.isNotBlank(link.operationRef())) { linkObject.setOperationRef(link.operationRef()); isEmpty = false; } } if (StringUtils.isNotBlank(link.ref())) { linkObject.set$ref(link.ref()); isEmpty = false; } if (link.extensions() != null && link.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, link.extensions()); if (extensions != null) { if (openapi31) { extensions.forEach(linkObject::addExtension31); } else { extensions.forEach(linkObject::addExtension); } isEmpty = false; } } if (isEmpty) { return Optional.empty(); } Map linkParameters = getLinkParameters(link.parameters()); if (linkParameters.size() > 0) { linkObject.setParameters(linkParameters); } if (StringUtils.isNotBlank(link.requestBody())) { JsonNode processedValue = null; try { if (openapi31) { processedValue = Json31.mapper().readTree(link.requestBody()); } else { processedValue = Json.mapper().readTree(link.requestBody()); } } catch (Exception e) { // not a json string } if (processedValue == null) { linkObject.requestBody(link.requestBody()); } else { linkObject.requestBody(processedValue); } } return Optional.of(linkObject); } public static Map getLinkParameters(LinkParameter[] linkParameter) { Map linkParametersMap = new HashMap<>(); if (linkParameter == null) { return linkParametersMap; } for (LinkParameter parameter : linkParameter) { if (StringUtils.isNotBlank(parameter.name())) { linkParametersMap.put(parameter.name(), parameter.expression()); } } return linkParametersMap; } public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, JsonView jsonViewAnnotation) { return getHeaders(annotationHeaders, null, jsonViewAnnotation); } public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, Components components, JsonView jsonViewAnnotation) { return getHeaders(annotationHeaders, components, jsonViewAnnotation, false); } public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, JsonView jsonViewAnnotation, boolean openapi31) { return getHeaders(annotationHeaders, null, jsonViewAnnotation, openapi31); } public static Optional> getHeaders(io.swagger.v3.oas.annotations.headers.Header[] annotationHeaders, Components components, JsonView jsonViewAnnotation, boolean openapi31) { if (annotationHeaders == null) { return Optional.empty(); } Map headers = new HashMap<>(); for (io.swagger.v3.oas.annotations.headers.Header header : annotationHeaders) { getHeader(header, components, jsonViewAnnotation, openapi31).ifPresent(headerResult -> headers.put(header.name(), headerResult)); } if (headers.size() == 0) { return Optional.empty(); } return Optional.of(headers); } public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, JsonView jsonViewAnnotation) { return getHeader(header, null, jsonViewAnnotation); } public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, Components components, JsonView jsonViewAnnotation) { return getHeader(header, components, jsonViewAnnotation, false); } public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, JsonView jsonViewAnnotation, boolean openapi31) { return getHeader(header, null, jsonViewAnnotation, openapi31); } public static Optional
getHeader(io.swagger.v3.oas.annotations.headers.Header header, Components components, JsonView jsonViewAnnotation, boolean openapi31) { if (header == null || header.hidden()) { return Optional.empty(); } Header headerObject = new Header(); boolean isEmpty = !StringUtils.isNotBlank(header.name()); if (StringUtils.isNotBlank(header.description())) { headerObject.setDescription(header.description()); isEmpty = false; } if (StringUtils.isNotBlank(header.ref())) { headerObject.set$ref(header.ref()); isEmpty = false; } if (StringUtils.isNotBlank(header.example())) { try { headerObject.setExample(Json.mapper().readTree(header.example())); } catch (IOException e) { headerObject.setExample(header.example()); } } if (header.deprecated()) { headerObject.setDeprecated(header.deprecated()); } if (header.required()) { headerObject.setRequired(header.required()); isEmpty = false; } Map exampleMap = new LinkedHashMap<>(); if (header.examples().length == 1 && StringUtils.isBlank(header.examples()[0].name())) { Optional exampleOptional = AnnotationsUtils.getExample(header.examples()[0], true); exampleOptional.ifPresent(headerObject::setExample); } else { for (ExampleObject exampleObject : header.examples()) { AnnotationsUtils.getExample(exampleObject).ifPresent(example -> exampleMap.put(exampleObject.name(), example)); } } if (!exampleMap.isEmpty()) { headerObject.setExamples(exampleMap); } headerObject.setStyle(Header.StyleEnum.SIMPLE); if (header.schema() != null) { if (header.schema().implementation().equals(Void.class)) { AnnotationsUtils.getSchemaFromAnnotation(header.schema(), jsonViewAnnotation, openapi31).ifPresent( headerObject::setSchema); }else { AnnotatedType annotatedType = new AnnotatedType() .type(getSchemaType(header.schema())) .resolveAsRef(true) .skipOverride(true) .jsonViewAnnotation(jsonViewAnnotation); final ResolvedSchema resolvedSchema = ModelConverters.getInstance(openapi31).resolveAsResolvedSchema(annotatedType); if (resolvedSchema.schema != null) { headerObject.setSchema(resolvedSchema.schema); } if (resolvedSchema.referencedSchemas != null && components != null) { resolvedSchema.referencedSchemas.forEach(components::addSchemas); } } } if (hasArrayAnnotation(header.array())){ AnnotationsUtils.getArraySchema(header.array(), components, jsonViewAnnotation, openapi31, null, true).ifPresent( headerObject::setSchema); } setHeaderExplode(headerObject, header); if (isEmpty) { return Optional.empty(); } return Optional.of(headerObject); } public static void setHeaderExplode (Header header, io.swagger.v3.oas.annotations.headers.Header h) { if (isHeaderExplodable(h, header)) { if (Explode.TRUE.equals(h.explode())) { header.setExplode(Boolean.TRUE); } else if (Explode.FALSE.equals(h.explode())) { header.setExplode(Boolean.FALSE); } } } private static boolean isHeaderExplodable(io.swagger.v3.oas.annotations.headers.Header h, Header header) { io.swagger.v3.oas.annotations.media.Schema schema = hasArrayAnnotation(h.array()) ? h.array().schema() : h.schema(); boolean explode = true; if (schema != null) { Class implementation = schema.implementation(); if (implementation == Void.class) { if (!schema.type().equals("object") && !schema.type().equals("array")) { explode = false; } } } return explode; } public static void addEncodingToMediaType(MediaType mediaType, io.swagger.v3.oas.annotations.media.Encoding encoding, JsonView jsonViewAnnotation) { addEncodingToMediaType(mediaType, encoding, jsonViewAnnotation, false); } public static void addEncodingToMediaType(MediaType mediaType, io.swagger.v3.oas.annotations.media.Encoding encoding, JsonView jsonViewAnnotation, boolean openapi31) { if (encoding == null) { return; } if (StringUtils.isNotBlank(encoding.name())) { Encoding encodingObject = new Encoding(); if (StringUtils.isNotBlank(encoding.contentType())) { encodingObject.setContentType(encoding.contentType()); } if (StringUtils.isNotBlank(encoding.style())) { encodingObject.setStyle(Encoding.StyleEnum.valueOf(encoding.style())); } if (encoding.explode()) { encodingObject.setExplode(encoding.explode()); } if (encoding.allowReserved()) { encodingObject.setAllowReserved(encoding.allowReserved()); } if (encoding.headers() != null) { getHeaders(encoding.headers(), null, jsonViewAnnotation, openapi31).ifPresent(encodingObject::headers); } if (encoding.extensions() != null && encoding.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, encoding.extensions()); if (extensions != null) { if (openapi31) { extensions.forEach(encodingObject::addExtension31); } else { extensions.forEach(encodingObject::addExtension); } } } mediaType.addEncoding(encoding.name(), encodingObject); } } public static Type getSchemaType(io.swagger.v3.oas.annotations.media.Schema schema) { return getSchemaType(schema, false); } public static Type getSchemaType(io.swagger.v3.oas.annotations.media.Schema schema, boolean nullIfNotFound) { if (schema == null) { if (nullIfNotFound) { return null; } return String.class; } String schemaType = schema.type(); String schemaFormat = schema.format(); Class schemaImplementation = schema.implementation(); if (!schemaImplementation.equals(Void.class)) { return schemaImplementation; } else if (StringUtils.isBlank(schemaType)) { if (nullIfNotFound) { return null; } return String.class; } switch (schemaType) { case "number": if ("float".equals(schemaFormat)) { return Float.class; } else if ("double".equals(schemaFormat)) { return Double.class; } else { return BigDecimal.class; } case "integer": if ("int32".equals(schemaFormat)) { return Integer.class; } else { return Long.class; } case "boolean": return Boolean.class; case "string": return String.class; default: if (nullIfNotFound) { return null; } return String.class; } } public static Optional getContent(io.swagger.v3.oas.annotations.media.Content[] annotationContents, String[] classTypes, String[] methodTypes, Schema schema, Components components, JsonView jsonViewAnnotation) { return getContent(annotationContents, classTypes, methodTypes, schema, components, jsonViewAnnotation, false); } public static Schema clone(Schema schema, boolean openapi31) { if(schema == null) return schema; try { String cloneName = schema.getName(); if(openapi31) { schema = Json31.mapper().readValue(Json31.pretty(schema), Schema.class); } else { schema = Json.mapper().readValue(Json.pretty(schema), Schema.class); } schema.setName(cloneName); } catch (IOException e) { LOGGER.error("Could not clone schema", e); } return schema; } public static Optional getContent(io.swagger.v3.oas.annotations.media.Content[] annotationContents, String[] classTypes, String[] methodTypes, Schema schema, Components components, JsonView jsonViewAnnotation, boolean openapi31) { if (annotationContents == null || annotationContents.length == 0) { return Optional.empty(); } //Encapsulating Content model Content content = new Content(); for (io.swagger.v3.oas.annotations.media.Content annotationContent : annotationContents) { MediaType mediaType = new MediaType(); if (components != null) { Optional annSchema = getSchema(annotationContent, components, jsonViewAnnotation, openapi31); if (annSchema.isPresent()) { // mediaType.setSchema(clone((Schema)annSchema.get(), openapi31)); mediaType.setSchema((Schema)annSchema.get()); } if (annotationContent.schemaProperties().length > 0) { if (mediaType.getSchema() == null) { mediaType.schema(openapi31 ? new JsonSchema().typesItem("object") : new Schema().type("object")); } Schema oSchema = mediaType.getSchema(); for (SchemaProperty sp: annotationContent.schemaProperties()) { Class schemaImplementation = sp.schema().implementation(); boolean isArray = false; if (schemaImplementation == Void.class) { schemaImplementation = sp.array().schema().implementation(); if (schemaImplementation != Void.class) { isArray = true; } } getSchema(sp.schema(), sp.array(), isArray, schemaImplementation, components, jsonViewAnnotation, openapi31) .ifPresent(s -> { if ("array".equals(oSchema.getType())) { oSchema.getItems().addProperty(sp.name(), s); } else { oSchema.addProperty(sp.name(), s); } }); } } Optional arraySchemaResult = getArraySchema(annotationContent.additionalPropertiesArraySchema(), components, jsonViewAnnotation, openapi31, null, true); if (arraySchemaResult.isPresent()) { if ("array".equals(mediaType.getSchema().getType())) { mediaType.getSchema().getItems().additionalProperties(arraySchemaResult.get()); } else { mediaType.getSchema().additionalProperties(arraySchemaResult.get()); } } else { if ( hasSchemaAnnotation(annotationContent.additionalPropertiesSchema()) && mediaType.getSchema() != null && !Boolean.TRUE.equals(mediaType.getSchema().getAdditionalProperties()) && !Boolean.FALSE.equals(mediaType.getSchema().getAdditionalProperties())) { getSchemaFromAnnotation(annotationContent.additionalPropertiesSchema(), components, jsonViewAnnotation, openapi31) .ifPresent(s -> { if ("array".equals(mediaType.getSchema().getType())) { mediaType.getSchema().getItems().additionalProperties(s); } else { mediaType.getSchema().additionalProperties(s); } } ); } } } else { mediaType.setSchema(schema); } ExampleObject[] examples = annotationContent.examples(); if (examples.length == 1 && StringUtils.isBlank(examples[0].name())) { getExample(examples[0], true).ifPresent(exampleObject -> mediaType.example(exampleObject.getValue())); } else { for (ExampleObject example : examples) { getExample(example).ifPresent(exampleObject -> mediaType.addExamples(example.name(), exampleObject)); } } if (annotationContent.extensions() != null && annotationContent.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, annotationContent.extensions()); if (extensions != null) { if (openapi31) { extensions.forEach(mediaType::addExtension31); } else { extensions.forEach(mediaType::addExtension); } } } io.swagger.v3.oas.annotations.media.Encoding[] encodings = annotationContent.encoding(); for (io.swagger.v3.oas.annotations.media.Encoding encoding : encodings) { addEncodingToMediaType(mediaType, encoding, jsonViewAnnotation, openapi31); } if (StringUtils.isNotBlank(annotationContent.mediaType())) { content.addMediaType(annotationContent.mediaType(), mediaType); } else { applyTypes(classTypes, methodTypes, content, mediaType); } DependentSchema[] dependentSchemas = annotationContent.dependentSchemas(); if (dependentSchemas.length > 0) { final Map dependentSchemaMap = new LinkedHashMap<>(); for (DependentSchema dependentSchema : dependentSchemas) { if ("array".equals(mediaType.getSchema().getType())) { getArraySchema(dependentSchema.array(), components, jsonViewAnnotation, openapi31).ifPresent(arraySchema -> dependentSchemaMap.put(dependentSchema.name(), arraySchema)); } else { getSchemaFromAnnotation(dependentSchema.schema(), components, jsonViewAnnotation, openapi31).ifPresent(schema1 -> dependentSchemaMap.put(dependentSchema.name(), schema1)); } } mediaType.getSchema().setDependentSchemas(dependentSchemaMap); } if (mediaType.getSchema() != null) { getSchemaFromAnnotation(annotationContent.contentSchema(), components, jsonViewAnnotation, openapi31).ifPresent(mediaType.getSchema()::setContentSchema); getSchemaFromAnnotation(annotationContent.propertyNames(), components, jsonViewAnnotation, openapi31).ifPresent(mediaType.getSchema()::setPropertyNames); getSchemaFromAnnotation(annotationContent._if(), components, jsonViewAnnotation, openapi31).ifPresent(mediaType.getSchema()::setIf); getSchemaFromAnnotation(annotationContent._then(), components, jsonViewAnnotation, openapi31).ifPresent(mediaType.getSchema()::setThen); getSchemaFromAnnotation(annotationContent._else(), components, jsonViewAnnotation, openapi31).ifPresent(mediaType.getSchema()::setElse); getSchemaFromAnnotation(annotationContent.not(), components, jsonViewAnnotation, openapi31).ifPresent(mediaType.getSchema()::setNot); } if (annotationContent.oneOf().length > 0) { for (io.swagger.v3.oas.annotations.media.Schema oneOfSchema : annotationContent.oneOf()) { getSchemaFromAnnotation(oneOfSchema, components, jsonViewAnnotation).ifPresent(mediaType.getSchema()::addOneOfItem); } } if (annotationContent.anyOf().length > 0) { for (io.swagger.v3.oas.annotations.media.Schema anyOfSchema : annotationContent.anyOf()) { getSchemaFromAnnotation(anyOfSchema, components, jsonViewAnnotation).ifPresent(mediaType.getSchema()::addAnyOfItem); } } if (annotationContent.allOf().length > 0) { for (io.swagger.v3.oas.annotations.media.Schema anyOfSchema : annotationContent.allOf()) { getSchemaFromAnnotation(anyOfSchema, components, jsonViewAnnotation).ifPresent(mediaType.getSchema()::addAllOfItem); } } } if (content.size() == 0) { return Optional.empty(); } return Optional.of(content); } public static Optional getSchema(io.swagger.v3.oas.annotations.media.Content annotationContent, Components components, JsonView jsonViewAnnotation) { return getSchema(annotationContent, components, jsonViewAnnotation, false); } public static Optional getSchema(io.swagger.v3.oas.annotations.media.Content annotationContent, Components components, JsonView jsonViewAnnotation, boolean openapi31) { Class schemaImplementation = annotationContent.schema().implementation(); boolean isArray = false; if (schemaImplementation == Void.class) { schemaImplementation = annotationContent.array().schema().implementation(); if (schemaImplementation != Void.class) { isArray = true; } } return getSchema(annotationContent.schema(), annotationContent.array(), isArray, schemaImplementation, components, jsonViewAnnotation, openapi31); } public static Optional getSchema(io.swagger.v3.oas.annotations.media.Schema schemaAnnotation, io.swagger.v3.oas.annotations.media.ArraySchema arrayAnnotation, boolean isArray, Class schemaImplementation, Components components, JsonView jsonViewAnnotation) { return getSchema(schemaAnnotation, arrayAnnotation, isArray, schemaImplementation, components, jsonViewAnnotation, false); } public static Optional getSchema(io.swagger.v3.oas.annotations.media.Schema schemaAnnotation, io.swagger.v3.oas.annotations.media.ArraySchema arrayAnnotation, boolean isArray, Class schemaImplementation, Components components, JsonView jsonViewAnnotation, boolean openapi31) { if (schemaImplementation != Void.class) { Schema schemaObject = resolveSchemaFromType(schemaImplementation, components, jsonViewAnnotation, openapi31, schemaAnnotation, arrayAnnotation, null); if (StringUtils.isNotBlank(schemaAnnotation.format())) { schemaObject.setFormat(schemaAnnotation.format()); } if (isArray) { Optional arraySchema = AnnotationsUtils.getArraySchema(arrayAnnotation, components, jsonViewAnnotation, openapi31, null); if (arraySchema.isPresent()) { arraySchema.get().setItems(schemaObject); return arraySchema; } else { return Optional.empty(); } } else { return Optional.of(schemaObject); } } else { Optional schemaFromAnnotation = AnnotationsUtils.getSchemaFromAnnotation(schemaAnnotation, components, jsonViewAnnotation, openapi31); if (schemaFromAnnotation.isPresent()) { if (StringUtils.isBlank(schemaFromAnnotation.get().get$ref()) && StringUtils.isBlank(schemaFromAnnotation.get().getType()) && !(schemaFromAnnotation.get() instanceof ComposedSchema)) { // default to string schemaFromAnnotation.get().setType("string"); } return Optional.of(schemaFromAnnotation.get()); } else { Optional arraySchemaFromAnnotation = AnnotationsUtils.getArraySchema(arrayAnnotation, components, jsonViewAnnotation, openapi31, null); if (arraySchemaFromAnnotation.isPresent()) { if (arraySchemaFromAnnotation.get().getItems() != null && StringUtils.isBlank(arraySchemaFromAnnotation.get().getItems().get$ref()) && StringUtils.isBlank(arraySchemaFromAnnotation.get().getItems().getType())) { // default to string arraySchemaFromAnnotation.get().getItems().setType("string"); } return Optional.of(arraySchemaFromAnnotation.get()); } } } return Optional.empty(); } public static void applyTypes(String[] classTypes, String[] methodTypes, Content content, MediaType mediaType) { if (methodTypes != null && methodTypes.length > 0) { for (String value : methodTypes) { content.addMediaType(value, mediaType); } } else if (classTypes != null && classTypes.length > 0) { for (String value : classTypes) { content.addMediaType(value, mediaType); } } else { content.addMediaType(ParameterProcessor.MEDIA_TYPE, mediaType); } } public static io.swagger.v3.oas.annotations.media.Schema getSchemaAnnotation(Annotated a) { if (a == null) { return null; } io.swagger.v3.oas.annotations.media.ArraySchema arraySchema = a.getAnnotation(io.swagger.v3.oas.annotations.media.ArraySchema.class); if (arraySchema != null) { return arraySchema.schema(); } else { return a.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); } } public static io.swagger.v3.oas.annotations.media.Schema getSchemaDeclaredAnnotation(Annotated a) { if (a == null) { return null; } io.swagger.v3.oas.annotations.media.ArraySchema arraySchema = a.getRawType().getDeclaredAnnotation(io.swagger.v3.oas.annotations.media.ArraySchema.class); if (arraySchema != null) { return arraySchema.schema(); } else { return a.getRawType().getDeclaredAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); } } public static io.swagger.v3.oas.annotations.media.Schema getSchemaAnnotation(Class cls) { if (cls == null) { return null; } io.swagger.v3.oas.annotations.media.Schema mp = null; io.swagger.v3.oas.annotations.media.ArraySchema as = cls.getAnnotation(io.swagger.v3.oas.annotations.media.ArraySchema.class); if (as != null) { mp = as.schema(); } else { mp = cls.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); } return mp; } public static io.swagger.v3.oas.annotations.media.Schema getSchemaDeclaredAnnotation(Class cls) { if (cls == null) { return null; } io.swagger.v3.oas.annotations.media.Schema mp = null; io.swagger.v3.oas.annotations.media.ArraySchema as = cls.getDeclaredAnnotation(io.swagger.v3.oas.annotations.media.ArraySchema.class); if (as != null) { mp = as.schema(); } else { mp = cls.getDeclaredAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); } return mp; } public static Map getExtensions(Extension... extensions) { return getExtensions(false, true, extensions); } public static Map getExtensions(boolean openapi31, Extension... extensions) { return getExtensions(openapi31, true, extensions); } public static Map getExtensions(boolean openapi31, boolean usePrefix, Extension... extensions) { final Map map = new HashMap<>(); for (Extension extension : extensions) { final String name = extension.name(); String decoratedName = usePrefix ? StringUtils.prependIfMissing(name, "x-") : name; final String key = name.isEmpty() ? name : decoratedName; for (ExtensionProperty property : extension.properties()) { final String propertyName = property.name(); final String propertyValue = property.value(); JsonNode processedValue; final boolean propertyAsJson = property.parseValue(); if (StringUtils.isNotBlank(propertyName) && StringUtils.isNotBlank(propertyValue)) { if (key.isEmpty()) { if (propertyAsJson) { try { if (openapi31) { processedValue = Json31.mapper().readTree(propertyValue); } else { processedValue = Json.mapper().readTree(propertyValue); } decoratedName = usePrefix ? StringUtils.prependIfMissing(propertyName, "x-") : propertyName; map.put(decoratedName, processedValue); } catch (Exception e) { decoratedName = usePrefix ? StringUtils.prependIfMissing(propertyName, "x-") : propertyName; map.put(decoratedName, propertyValue); } } else { decoratedName = usePrefix ? StringUtils.prependIfMissing(propertyName, "x-") : propertyName; map.put(decoratedName, propertyValue); } } else { Object value = map.get(key); if (!(value instanceof Map)) { value = new HashMap(); map.put(key, value); } @SuppressWarnings("unchecked") final Map mapValue = (Map) value; if (propertyAsJson) { try { if (openapi31) { processedValue = Json31.mapper().readTree(propertyValue); } else { processedValue = Json.mapper().readTree(propertyValue); } mapValue.put(propertyName, processedValue); } catch (Exception e) { mapValue.put(propertyName, propertyValue); } } else { mapValue.put(propertyName, propertyValue); } } } } } return map; } public static io.swagger.v3.oas.annotations.media.Schema getSchemaAnnotation(Annotation... annotations) { if (annotations == null) { return null; } for (Annotation annotation : annotations) { if (annotation instanceof io.swagger.v3.oas.annotations.media.Schema) { return (io.swagger.v3.oas.annotations.media.Schema) annotation; } } return null; } public static io.swagger.v3.oas.annotations.media.ArraySchema getArraySchemaAnnotation(Annotation... annotations) { if (annotations == null) { return null; } for (Annotation annotation : annotations) { if (annotation instanceof io.swagger.v3.oas.annotations.media.ArraySchema) { return (io.swagger.v3.oas.annotations.media.ArraySchema) annotation; } } return null; } public static T getAnnotation(Class cls, Annotation... annotations) { if (annotations == null) { return null; } for (Annotation annotation : annotations) { if (cls.isAssignableFrom(annotation.getClass())) { return (T)annotation; } } return null; } public static Annotation[] removeAnnotations(Annotation[] annotations, Class ... classes) { if (annotations == null) { return null; } List result = new ArrayList<>(); for (Annotation annotation : annotations) { boolean found = false; for (Class cls : classes) { if (cls.isAssignableFrom(annotation.getClass())) { found = true; } } if (!found) { result.add(annotation); } } return result.toArray(new Annotation[result.size()]); } public static void updateAnnotation(Class clazz, io.swagger.v3.oas.annotations.media.Schema newAnnotation) { try { Field field = Class.class.getDeclaredField("annotations"); field.setAccessible(true); Map, Annotation> annotations = (Map, Annotation>) field.get(clazz); annotations.put(io.swagger.v3.oas.annotations.media.Schema.class, newAnnotation); } catch (NoSuchFieldException e) { // } catch (IllegalAccessException e) { // } } public static Annotation mergeSchemaAnnotations( Annotation[] ctxAnnotations, JavaType type) { return mergeSchemaAnnotations(ctxAnnotations, type, false); } /* * returns null if no annotations, otherwise either ArraySchema or Schema */ public static Annotation mergeSchemaAnnotations( Annotation[] ctxAnnotations, JavaType type, boolean contextWins) { // get type array and schema io.swagger.v3.oas.annotations.media.Schema tS = type.getRawClass().getDeclaredAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); if (!hasSchemaAnnotation(tS)) { tS = null; } io.swagger.v3.oas.annotations.media.ArraySchema tA = type.getRawClass().getDeclaredAnnotation(io.swagger.v3.oas.annotations.media.ArraySchema.class); if (!hasArrayAnnotation(tA)) { tA = null; } io.swagger.v3.oas.annotations.media.Schema tAs = tA == null ? null : tA.schema(); if (!hasSchemaAnnotation(tAs)) { tAs = null; } // get ctx array and schema io.swagger.v3.oas.annotations.media.Schema cS = getSchemaAnnotation(ctxAnnotations); if (!hasSchemaAnnotation(cS)) { cS = null; } io.swagger.v3.oas.annotations.media.ArraySchema cA = getArraySchemaAnnotation(ctxAnnotations); if (!hasArrayAnnotation(cA)) { cA = null; } io.swagger.v3.oas.annotations.media.Schema cAs = cA == null ? null : cA.schema(); if (!hasSchemaAnnotation(cAs)) { cAs = null; } if (tS == null && tA == null && cS == null && cA == null) { return null; } else if (tS == null && tA == null && cS != null) { return cS; } else if (tS == null && tA == null && cS == null && cA != null) { return cA; } else if (tS == null && tA != null && cS == null && cA == null) { return tA; } else if (tS == null && tA != null && cS != null && cA == null) { if (tAs != null) { return tA; } return mergeArrayWithSchemaAnnotation(tA, cS); } else if (tS != null && tA == null && cS == null && cA != null) { if (cAs != null) { return cA; } return mergeArrayWithSchemaAnnotation(cA, tS); } else if (tA != null && cA != null) { if (contextWins) { return mergeArraySchemaAnnotations(tA, cA); } return mergeArraySchemaAnnotations(cA, tA); } else if (tS != null && cS == null && cA == null) { return tS; } else if (tS != null && cS != null) { if (contextWins) { return mergeSchemaAnnotations(cS, tS); } return mergeSchemaAnnotations(tS, cS); } else { return tS; } } public static io.swagger.v3.oas.annotations.media.Schema mergeSchemaAnnotations( io.swagger.v3.oas.annotations.media.Schema master, io.swagger.v3.oas.annotations.media.Schema patch) { if (master == null) { return patch; } else if (patch == null) { return master; } else if (!hasSchemaAnnotation(patch)) { return master; } Annotation schema = new io.swagger.v3.oas.annotations.media.Schema() { @Override public Class implementation() { if (!master.implementation().equals(Void.class) || patch.implementation().equals(Void.class)) { return master.implementation(); } return patch.implementation(); } @Override public Class not() { if (!master.not().equals(Void.class) || patch.not().equals(Void.class)) { return master.not(); } return patch.not(); } @Override public Class[] oneOf() { if (master.oneOf().length > 0 || patch.oneOf().length == 0) { return master.oneOf(); } return patch.oneOf(); } @Override public Class[] anyOf() { if (master.anyOf().length > 0 || patch.anyOf().length == 0) { return master.anyOf(); } return patch.anyOf(); } @Override public Class[] allOf() { if (master.allOf().length > 0 || patch.allOf().length == 0) { return master.allOf(); } return patch.allOf(); } @Override public String name() { if (StringUtils.isNotBlank(master.name()) || StringUtils.isBlank(patch.name())) { return master.name(); } return patch.name(); } @Override public String title() { if (StringUtils.isNotBlank(master.title()) || StringUtils.isBlank(patch.title())) { return master.title(); } return patch.title(); } @Override public double multipleOf() { if (master.multipleOf() != 0 || patch.multipleOf() == 0) { return master.multipleOf(); } return patch.multipleOf(); } @Override public String maximum() { if (StringUtils.isNotBlank(master.maximum()) || StringUtils.isBlank(patch.maximum())) { return master.maximum(); } return patch.maximum(); } @Override public boolean exclusiveMaximum() { if (master.exclusiveMaximum() || !patch.exclusiveMaximum()) { return master.exclusiveMaximum(); } return patch.exclusiveMaximum(); } @Override public String minimum() { if (StringUtils.isNotBlank(master.minimum()) || StringUtils.isBlank(patch.minimum())) { return master.minimum(); } return patch.minimum(); } @Override public boolean exclusiveMinimum() { if (master.exclusiveMinimum() || !patch.exclusiveMinimum()) { return master.exclusiveMinimum(); } return patch.exclusiveMinimum(); } @Override public int maxLength() { if (( master.maxLength() != Integer.MAX_VALUE && master.maxLength() > 0) || (patch.maxLength() == Integer.MAX_VALUE || patch.maxLength() == 0) ) { return master.maxLength(); } return patch.maxLength(); } @Override public int minLength() { if (master.minLength() != 0 || patch.minLength() == 0) { return master.minLength(); } return patch.minLength(); } @Override public String pattern() { if (StringUtils.isNotBlank(master.pattern()) || StringUtils.isBlank(patch.pattern())) { return master.pattern(); } return patch.pattern(); } @Override public int maxProperties() { if (master.maxProperties() != 0 || patch.maxProperties() == 0) { return master.maxProperties(); } return patch.maxProperties(); } @Override public int minProperties() { if (master.minProperties() != 0 || patch.minProperties() == 0) { return master.minProperties(); } return patch.minProperties(); } @Override public String[] requiredProperties() { if (master.requiredProperties().length > 0 || patch.requiredProperties().length == 0) { return master.requiredProperties(); } return patch.requiredProperties(); } @Override public boolean required() { if (master.required() || !patch.required()) { return master.required(); } return patch.required(); } @Override public RequiredMode requiredMode() { if (!master.requiredMode().equals(RequiredMode.AUTO) || patch.requiredMode().equals(RequiredMode.AUTO)) { return master.requiredMode(); } return patch.requiredMode(); } @Override public String description() { if (StringUtils.isNotBlank(master.description()) || StringUtils.isBlank(patch.description())) { return master.description(); } return patch.description(); } @Override public String format() { if (StringUtils.isNotBlank(master.format()) || StringUtils.isBlank(patch.format())) { return master.format(); } return patch.format(); } @Override public String ref() { if (StringUtils.isNotBlank(master.ref()) || StringUtils.isBlank(patch.ref())) { return master.ref(); } return patch.ref(); } @Override public boolean nullable() { if (master.nullable() || !patch.nullable()) { return master.nullable(); } return patch.nullable(); } @Override public boolean readOnly() { if (master.readOnly() || !patch.readOnly()) { return master.readOnly(); } return patch.readOnly(); } @Override public boolean writeOnly() { if (master.writeOnly() || !patch.writeOnly()) { return master.writeOnly(); } return patch.writeOnly(); } @Override public AccessMode accessMode() { if (!master.accessMode().equals(AccessMode.AUTO) || patch.accessMode().equals(AccessMode.AUTO)) { return master.accessMode(); } return patch.accessMode(); } @Override public String example() { if (StringUtils.isNotBlank(master.example()) || StringUtils.isBlank(patch.example())) { return master.example(); } return patch.example(); } @Override public io.swagger.v3.oas.annotations.ExternalDocumentation externalDocs() { if (getExternalDocumentation(master.externalDocs()).isPresent() || !getExternalDocumentation(patch.externalDocs()).isPresent()) { return master.externalDocs(); } return patch.externalDocs(); } @Override public boolean deprecated() { if (master.deprecated() || !patch.deprecated()) { return master.deprecated(); } return patch.deprecated(); } @Override public String type() { if (StringUtils.isNotBlank(master.type()) || StringUtils.isBlank(patch.type())) { return master.type(); } return patch.type(); } @Override public String[] allowableValues() { if (master.allowableValues().length > 0 || patch.allowableValues().length == 0) { return master.allowableValues(); } return patch.allowableValues(); } @Override public String defaultValue() { if (!DEFAULT_SENTINEL.equals(master.defaultValue())) { return master.defaultValue(); } if (!DEFAULT_SENTINEL.equals(patch.defaultValue())) { return patch.defaultValue(); } return master.defaultValue(); } @Override public String discriminatorProperty() { if (StringUtils.isNotBlank(master.discriminatorProperty()) || StringUtils.isBlank(patch.discriminatorProperty())) { return master.discriminatorProperty(); } return patch.discriminatorProperty(); } @Override public DiscriminatorMapping[] discriminatorMapping() { if (master.discriminatorMapping().length > 0 || patch.discriminatorMapping().length == 0) { return master.discriminatorMapping(); } return patch.discriminatorMapping(); } @Override public boolean hidden() { if (master.hidden() || !patch.hidden()) { return master.hidden(); } return patch.hidden(); } @Override public boolean enumAsRef() { if (master.enumAsRef() || !patch.enumAsRef()) { return master.enumAsRef(); } return patch.enumAsRef(); } @Override public Class[] subTypes() { if (master.subTypes().length > 0 || patch.subTypes().length == 0) { return master.subTypes(); } return patch.subTypes(); } @Override public Extension[] extensions() { if (master.extensions().length > 0 || patch.extensions().length == 0) { return master.extensions(); } return patch.extensions(); } @Override public Class[] prefixItems() { if (master.prefixItems().length > 0 || patch.prefixItems().length == 0) { return master.prefixItems(); } return patch.prefixItems(); } @Override public String[] types() { if (master.types().length > 0 || patch.types().length == 0) { return master.types(); } return patch.types(); } @Override public int exclusiveMaximumValue() { if (master.exclusiveMaximumValue() != 0 || patch.exclusiveMaximumValue() == 0) { return master.exclusiveMaximumValue(); } return patch.exclusiveMaximumValue(); } @Override public int exclusiveMinimumValue() { if (master.exclusiveMinimumValue() != 0 || patch.exclusiveMinimumValue() == 0) { return master.exclusiveMaximumValue(); } return patch.exclusiveMinimumValue(); } @Override public Class contains() { if (!master.contains().equals(Void.class) || patch.contains().equals(Void.class)) { return master.contains(); } return patch.contains(); } @Override public String $id() { if (StringUtils.isNotBlank(master.$id()) || StringUtils.isBlank(patch.$id())) { return master.$id(); } return patch.$id(); } @Override public String $schema() { if (StringUtils.isNotBlank(master.$schema()) || StringUtils.isBlank(patch.$schema())) { return master.$schema(); } return patch.$schema(); } @Override public String $anchor() { if (StringUtils.isNotBlank(master.$anchor()) || StringUtils.isBlank(patch.$anchor())) { return master.$anchor(); } return patch.$anchor(); } @Override public String $vocabulary() { if (StringUtils.isNotBlank(master.$vocabulary()) || StringUtils.isBlank(patch.$vocabulary())) { return master.$vocabulary(); } return patch.$vocabulary(); } @Override public String $dynamicAnchor() { if (StringUtils.isNotBlank(master.$dynamicAnchor()) || StringUtils.isBlank(patch.$dynamicAnchor())) { return master.$dynamicAnchor(); } return patch.$dynamicAnchor(); } @Override public String $dynamicRef() { if (StringUtils.isNotBlank(master.$dynamicRef()) || StringUtils.isBlank(patch.$dynamicRef())) { return master.$dynamicRef(); } return patch.$dynamicRef(); } @Override public String contentEncoding() { if (StringUtils.isNotBlank(master.contentEncoding()) || StringUtils.isBlank(patch.contentEncoding())) { return master.contentEncoding(); } return patch.contentEncoding(); } @Override public String contentMediaType() { if (StringUtils.isNotBlank(master.contentMediaType()) || StringUtils.isBlank(patch.contentMediaType())) { return master.contentMediaType(); } return patch.contentMediaType(); } @Override public Class contentSchema() { if (!master.contentSchema().equals(Void.class) || patch.contentSchema().equals(Void.class)) { return master.contentSchema(); } return patch.contentSchema(); } @Override public Class propertyNames() { if (!master.propertyNames().equals(Void.class) || patch.propertyNames().equals(Void.class)) { return master.propertyNames(); } return patch.propertyNames(); } @Override public int maxContains() { if (master.maxContains() != 0 || patch.maxContains() == 0) { return master.maxContains(); } return patch.maxContains(); } @Override public int minContains() { if (master.minContains() != 0 || patch.minContains() == 0) { return master.minContains(); } return patch.minContains(); } @Override public Class additionalItems() { if (!master.additionalItems().equals(Void.class) || patch.additionalItems().equals(Void.class)) { return master.additionalItems(); } return patch.additionalItems(); } @Override public Class unevaluatedItems() { if (!master.unevaluatedItems().equals(Void.class) || patch.unevaluatedItems().equals(Void.class)) { return master.unevaluatedItems(); } return patch.unevaluatedItems(); } @Override public Class _if() { if (!master._if().equals(Void.class) || patch._if().equals(Void.class)) { return master._if(); } return patch._if(); } @Override public Class _else() { if (!master._else().equals(Void.class) || patch._else().equals(Void.class)) { return master._else(); } return patch._else(); } @Override public Class then() { if (!master.then().equals(Void.class) || patch.then().equals(Void.class)) { return master.then(); } return patch.then(); } @Override public String $comment() { if (StringUtils.isNotBlank(master.$comment()) || StringUtils.isBlank(patch.$comment())) { return master.$comment(); } return patch.$comment(); } @Override public String[] examples() { if (master.examples().length > 0 || patch.examples().length == 0) { return master.examples(); } return patch.examples(); } @Override public Class[] exampleClasses() { if (master.exampleClasses().length > 0 || patch.exampleClasses().length == 0) { return master.exampleClasses(); } return patch.exampleClasses(); } @Override public String _const() { if (!master._const().equals(Void.class) || patch._const().equals(Void.class)) { return master._const(); } return patch._const(); } @Override public Class annotationType() { return io.swagger.v3.oas.annotations.media.Schema.class; } @Override public AdditionalPropertiesValue additionalProperties() { if (!master.additionalProperties().equals(AdditionalPropertiesValue.USE_ADDITIONAL_PROPERTIES_ANNOTATION) || patch.additionalProperties().equals(AdditionalPropertiesValue.USE_ADDITIONAL_PROPERTIES_ANNOTATION)) { return master.additionalProperties(); } return patch.additionalProperties(); } @Override public DependentRequired[] dependentRequiredMap() { if (master.dependentRequiredMap().length > 0 || patch.dependentRequiredMap().length == 0) { return master.dependentRequiredMap(); } return patch.dependentRequiredMap(); } @Override public StringToClassMapItem[] dependentSchemas() { if (master.dependentSchemas().length > 0 || patch.dependentSchemas().length == 0) { return master.dependentSchemas(); } return patch.dependentSchemas(); } @Override public StringToClassMapItem[] patternProperties() { if (master.patternProperties().length > 0 || patch.patternProperties().length == 0) { return master.patternProperties(); } return patch.patternProperties(); } @Override public StringToClassMapItem[] properties() { if (master.properties().length > 0 || patch.properties().length == 0) { return master.properties(); } return patch.properties(); } @Override public Class unevaluatedProperties() { if (!master.unevaluatedProperties().equals(Void.class) || patch.unevaluatedProperties().equals(Void.class)) { return master.unevaluatedProperties(); } return patch.unevaluatedProperties(); } @Override public Class additionalPropertiesSchema() { if (!master.additionalPropertiesSchema().equals(Void.class) || patch.additionalPropertiesSchema().equals(Void.class)) { return master.additionalPropertiesSchema(); } return patch.additionalPropertiesSchema(); } /* We always want the patch to take precedence in schema resolution behavior */ @Override public SchemaResolution schemaResolution() { if (!patch.schemaResolution().equals(SchemaResolution.DEFAULT) || master.schemaResolution().equals(SchemaResolution.DEFAULT)) { return patch.schemaResolution(); } return master.schemaResolution(); } }; return (io.swagger.v3.oas.annotations.media.Schema)schema; } public static io.swagger.v3.oas.annotations.media.ArraySchema mergeArraySchemaAnnotations( io.swagger.v3.oas.annotations.media.ArraySchema master, io.swagger.v3.oas.annotations.media.ArraySchema patch) { if (master == null) { return patch; } else if (patch == null) { return master; } else if (!hasArrayAnnotation(patch)) { return master; } Annotation newArraySchema = new io.swagger.v3.oas.annotations.media.ArraySchema() { @Override public Class annotationType() { return io.swagger.v3.oas.annotations.media.ArraySchema.class; } @Override public io.swagger.v3.oas.annotations.media.Schema schema() { io.swagger.v3.oas.annotations.media.Schema patchSchema = patch.schema(); if (!hasSchemaAnnotation(patchSchema)) { patchSchema = null; } if (patchSchema == null) { return master.schema(); } else { return mergeSchemaAnnotations(master.schema(), patch.schema()); } } @Override public io.swagger.v3.oas.annotations.media.Schema arraySchema() { io.swagger.v3.oas.annotations.media.Schema patchSchema = patch.arraySchema(); if (!hasSchemaAnnotation(patchSchema)) { patchSchema = null; } if (patchSchema == null) { return master.arraySchema(); } else { return mergeSchemaAnnotations(master.arraySchema(), patch.arraySchema()); } } @Override public int maxItems() { if (master.maxItems() != 0 || patch.maxItems() == 0) { return master.maxItems(); } return patch.maxItems(); } @Override public int minItems() { if (master.minItems() != 0 || patch.minItems() == 0) { return master.minItems(); } return patch.minItems(); } @Override public boolean uniqueItems() { if (master.uniqueItems() || !patch.uniqueItems()) { return master.uniqueItems(); } return patch.uniqueItems(); } @Override public Extension[] extensions() { if (master.extensions().length > 0 || patch.extensions().length == 0) { return master.extensions(); } return patch.extensions(); } @Override public io.swagger.v3.oas.annotations.media.Schema[] prefixItems() { if (master.prefixItems().length > 0 || patch.prefixItems().length == 0) { return master.prefixItems(); } return patch.prefixItems(); } @Override public io.swagger.v3.oas.annotations.media.Schema contains() { if (!master.contains().equals(Void.class) || patch.contains().equals(Void.class)) { return master.contains(); } return patch.contains(); } @Override public int maxContains() { if (master.maxContains() > 0) { return master.maxContains(); } return patch.maxContains(); } @Override public int minContains() { if (master.minContains() > 0) { return master.minContains(); } return patch.minContains(); } @Override public io.swagger.v3.oas.annotations.media.Schema unevaluatedItems() { if (!master.unevaluatedItems().equals(Void.class) || patch.unevaluatedItems().equals(Void.class)) { return master.unevaluatedItems(); } return patch.unevaluatedItems(); } @Override public io.swagger.v3.oas.annotations.media.Schema items() { if (!master.items().equals(Void.class) || patch.items().equals(Void.class)) { return master.items(); } return patch.items(); } }; return (io.swagger.v3.oas.annotations.media.ArraySchema)newArraySchema; } public static io.swagger.v3.oas.annotations.media.ArraySchema mergeArrayWithSchemaAnnotation( io.swagger.v3.oas.annotations.media.ArraySchema arraySchema, io.swagger.v3.oas.annotations.media.Schema schema) { if (arraySchema == null || schema == null) { return arraySchema; } if (!hasSchemaAnnotation(schema)) { return arraySchema; } Annotation newArraySchema = new io.swagger.v3.oas.annotations.media.ArraySchema() { @Override public Class annotationType() { return io.swagger.v3.oas.annotations.media.ArraySchema.class; } @Override public io.swagger.v3.oas.annotations.media.Schema items() { return arraySchema.items(); } @Override public io.swagger.v3.oas.annotations.media.Schema schema() { return schema; } @Override public io.swagger.v3.oas.annotations.media.Schema arraySchema() { return arraySchema.arraySchema(); } @Override public int maxItems() { return arraySchema.maxItems(); } @Override public int minItems() { return arraySchema.minItems(); } @Override public boolean uniqueItems() { return arraySchema.uniqueItems(); } @Override public Extension[] extensions() { return arraySchema.extensions(); } @Override public io.swagger.v3.oas.annotations.media.Schema contains() { return arraySchema.contains(); } @Override public int maxContains() { return arraySchema.maxContains(); } @Override public int minContains() { return arraySchema.minContains(); } @Override public io.swagger.v3.oas.annotations.media.Schema unevaluatedItems() { return arraySchema.unevaluatedItems(); } @Override public io.swagger.v3.oas.annotations.media.Schema[] prefixItems() { return arraySchema.prefixItems(); } }; return (io.swagger.v3.oas.annotations.media.ArraySchema)newArraySchema; } public static Schema.SchemaResolution resolveSchemaResolution(Schema.SchemaResolution globalSchemaResolution, io.swagger.v3.oas.annotations.media.Schema schemaAnnotation) { if (schemaAnnotation != null && !io.swagger.v3.oas.annotations.media.Schema.SchemaResolution.AUTO.equals(schemaAnnotation.schemaResolution())) { return Schema.SchemaResolution.valueOf(schemaAnnotation.schemaResolution().toString()); } return globalSchemaResolution; } public static boolean computeEnumAsRef(io.swagger.v3.oas.annotations.media.Schema ctxSchema, io.swagger.v3.oas.annotations.media.ArraySchema ctxArraySchema) { if (ctxSchema != null && ctxSchema.enumAsRef()) { return ctxSchema.enumAsRef(); } else if(ctxArraySchema != null && ctxArraySchema.schema() != null && ctxArraySchema.schema().enumAsRef()) { return ctxArraySchema.schema().enumAsRef(); } return false; } public static boolean areSiblingsAllowed(Schema.SchemaResolution resolvedSchemaResolution, boolean openapi31) { return Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution) || openapi31; } public static AnnotatedType addTypeWhenSiblingsAllowed(AnnotatedType aType, io.swagger.v3.oas.annotations.media.Schema ctxSchema, boolean areSiblingsAllowed) { if (areSiblingsAllowed && ctxSchema != null) { if (!Void.class.equals(ctxSchema.implementation())) { aType.setType(ctxSchema.implementation()); } else if (StringUtils.isNotBlank(ctxSchema.type())) { aType.setType(ctxSchema.type().getClass()); } } return aType; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ApiResponses31Deserializer.java ================================================ package io.swagger.v3.core.util; public class ApiResponses31Deserializer extends ApiResponsesDeserializer { public ApiResponses31Deserializer() { this.openapi31 = true; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ApiResponsesDeserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import java.io.IOException; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; public class ApiResponsesDeserializer extends JsonDeserializer { protected boolean openapi31; @Override public ApiResponses deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { final ObjectMapper mapper; if (openapi31) { mapper = Json31.mapper(); } else { mapper = Json.mapper(); } ApiResponses result = new ApiResponses(); JsonNode node = jp.getCodec().readTree(jp); ObjectNode objectNode = (ObjectNode) node; Map extensions = new LinkedHashMap<>(); for (Iterator it = objectNode.fieldNames(); it.hasNext(); ) { String childName = it.next(); JsonNode child = objectNode.get(childName); // if name start with `x-` consider it an extension if (childName.startsWith("x-")) { extensions.put(childName, mapper.convertValue(child, Object.class)); } else { result.put(childName, mapper.convertValue(child, ApiResponse.class)); } } if (!extensions.isEmpty()) { result.setExtensions(extensions); } return result; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Callback31Deserializer.java ================================================ package io.swagger.v3.core.util; public class Callback31Deserializer extends CallbackDeserializer { public Callback31Deserializer() { openapi31 = true; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/CallbackDeserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.callbacks.Callback; import java.io.IOException; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; public class CallbackDeserializer extends JsonDeserializer { protected boolean openapi31; @Override public Callback deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { final ObjectMapper mapper; if (openapi31) { mapper = Json31.mapper(); } else { mapper = Json.mapper(); } Callback result = new Callback(); JsonNode node = jp.getCodec().readTree(jp); ObjectNode objectNode = (ObjectNode)node; Map extensions = new LinkedHashMap<>(); for (Iterator it = objectNode.fieldNames(); it.hasNext(); ) { String childName = it.next(); JsonNode child = objectNode.get(childName); // if name start with `x-` consider it an extension if (childName.startsWith("x-")) { extensions.put(childName, mapper.convertValue(child, Object.class)); } else if (childName.equals("$ref")) { result.$ref(child.asText()); } else { result.put(childName, mapper.convertValue(child, PathItem.class)); } } if (!extensions.isEmpty()) { result.setExtensions(extensions); } return result; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Configuration.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import java.util.Map; import java.util.Set; public class Configuration { public enum GroupsValidationStrategy { @JsonProperty("default") DEFAULT("default"), @JsonProperty("never") NEVER("never"), @JsonProperty("always") ALWAYS("always"), @JsonProperty("neverIfNoContext") NEVER_IF_NO_CONTEXT("neverIfNoContext"); private String value; GroupsValidationStrategy(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } private Map userDefinedOptions; private OpenAPI openAPI; private Set modelConverterClasses; private String objectMapperProcessorClass; private Boolean openAPI31 = false; private Schema.SchemaResolution schemaResolution = Schema.SchemaResolution.DEFAULT; private String openAPIVersion = "3.0.1"; private GroupsValidationStrategy groupsValidationStrategy = GroupsValidationStrategy.DEFAULT; private String validatorProcessorClass; public OpenAPI getOpenAPI() { return openAPI; } public void setOpenAPI(OpenAPI openAPI) { this.openAPI = openAPI; } public Configuration openAPI(OpenAPI openAPI) { this.openAPI = openAPI; return this; } public Map getUserDefinedOptions() { return userDefinedOptions; } public void setUserDefinedOptions(Map userDefinedOptions) { this.userDefinedOptions = userDefinedOptions; } public Configuration userDefinedOptions(Map userDefinedOptions) { this.userDefinedOptions = userDefinedOptions; return this; } public Configuration objectMapperProcessorClass(String objectMapperProcessorClass) { this.objectMapperProcessorClass = objectMapperProcessorClass; return this; } public String getObjectMapperProcessorClass() { return objectMapperProcessorClass; } public void setObjectMapperProcessorClass(String objectMapperProcessorClass) { this.objectMapperProcessorClass = objectMapperProcessorClass; } public Set getModelConverterClasses() { return modelConverterClasses; } public void setModelConverterClassess(Set modelConverterClasses) { this.modelConverterClasses = modelConverterClasses; } public Configuration modelConverterClasses(Set modelConverterClasses) { this.modelConverterClasses = modelConverterClasses; return this; } public Boolean isOpenAPI31() { return openAPI31; } public void setOpenAPI31(Boolean openAPI31) { this.openAPI31 = openAPI31; } public Configuration openAPI31(Boolean openAPI31) { this.openAPI31 = openAPI31; return this; } public Schema.SchemaResolution getSchemaResolution() { return schemaResolution; } public void setSchemaResolution(Schema.SchemaResolution schemaResolution) { this.schemaResolution = schemaResolution; } public Configuration schemaResolution(Schema.SchemaResolution schemaResolution) { this.setSchemaResolution(schemaResolution); return this; } public String getOpenAPIVersion() { return openAPIVersion; } public void setOpenAPIVersion(String openAPIVersion) { this.openAPIVersion = openAPIVersion; } public Configuration openAPIVersion(String openAPIVersion) { this.setOpenAPIVersion(openAPIVersion); return this; } public void setModelConverterClasses(Set modelConverterClasses) { this.modelConverterClasses = modelConverterClasses; } public GroupsValidationStrategy getGroupsValidationStrategy() { return groupsValidationStrategy; } public void setGroupsValidationStrategy(GroupsValidationStrategy groupsValidationStrategy) { this.groupsValidationStrategy = groupsValidationStrategy; } public Configuration groupsValidationStrategy(GroupsValidationStrategy groupsValidationStrategy) { this.groupsValidationStrategy = groupsValidationStrategy; return this; } public String getValidatorProcessorClass() { return validatorProcessorClass; } public void setValidatorProcessorClass(String validatorProcessorClass) { this.validatorProcessorClass = validatorProcessorClass; } public Configuration validatorProcessorClass(String validatorProcessorClass) { this.validatorProcessorClass = validatorProcessorClass; return this; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Constants.java ================================================ package io.swagger.v3.core.util; public final class Constants { public static final String COMMA = ","; } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/DeserializationModule.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.module.SimpleModule; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.media.Encoding; import io.swagger.v3.oas.models.media.EncodingProperty; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityScheme; public class DeserializationModule extends SimpleModule { public DeserializationModule() { this.addDeserializer(Schema.class, new ModelDeserializer()); this.addDeserializer(Parameter.class, new ParameterDeserializer()); this.addDeserializer(Header.StyleEnum.class, new HeaderStyleEnumDeserializer()); this.addDeserializer(Encoding.StyleEnum.class, new EncodingStyleEnumDeserializer()); this.addDeserializer(EncodingProperty.StyleEnum.class, new EncodingPropertyStyleEnumDeserializer()); this.addDeserializer(SecurityScheme.class, new SecuritySchemeDeserializer()); this.addDeserializer(ApiResponses.class, new ApiResponsesDeserializer()); this.addDeserializer(Paths.class, new PathsDeserializer()); this.addDeserializer(Callback.class, new CallbackDeserializer()); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/DeserializationModule31.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; import com.fasterxml.jackson.databind.module.SimpleModule; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.media.Encoding; import io.swagger.v3.oas.models.media.EncodingProperty; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityScheme; public class DeserializationModule31 extends SimpleModule { public DeserializationModule31() { this.addDeserializer(Schema.class, new Model31Deserializer()); this.addDeserializer(Parameter.class, new Parameter31Deserializer()); this.addDeserializer(Header.StyleEnum.class, new HeaderStyleEnumDeserializer()); this.addDeserializer(Encoding.StyleEnum.class, new EncodingStyleEnumDeserializer()); this.addDeserializer(EncodingProperty.StyleEnum.class, new EncodingPropertyStyleEnumDeserializer()); this.addDeserializer(SecurityScheme.class, new SecurityScheme31Deserializer()); this.addDeserializer(ApiResponses.class, new ApiResponses31Deserializer()); this.addDeserializer(Paths.class, new Paths31Deserializer()); this.addDeserializer(Callback.class, new Callback31Deserializer()); this.setDeserializerModifier(new BeanDeserializerModifier() { @Override public JsonDeserializer modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer deserializer) { if (beanDesc.getBeanClass() == OpenAPI.class) { return new OpenAPI31Deserializer(deserializer); } return deserializer; } }); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/EncodingPropertyStyleEnumDeserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.models.media.EncodingProperty; import java.io.IOException; import java.util.Arrays; import java.util.stream.Collectors; public class EncodingPropertyStyleEnumDeserializer extends JsonDeserializer { @Override public EncodingProperty.StyleEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { JsonNode node = jp.getCodec().readTree(jp); if (node != null) { String value = node.asText(); return getStyleEnum(value); } return null; } private EncodingProperty.StyleEnum getStyleEnum(String value) { return Arrays.stream( EncodingProperty.StyleEnum.values()) .filter(i -> i.toString().equals(value)) .findFirst() .orElseThrow(() -> new RuntimeException( String.format("Can not deserialize value of type EncodingProperty.StyleEnum from String \"%s\": value not one of declared Enum instance names: %s", value, Arrays.stream(EncodingProperty.StyleEnum.values()).map(EncodingProperty.StyleEnum::toString).collect(Collectors.joining(", ", "[", "]"))))); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/EncodingStyleEnumDeserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.models.media.Encoding; import java.io.IOException; import java.util.Arrays; import java.util.stream.Collectors; public class EncodingStyleEnumDeserializer extends JsonDeserializer { @Override public Encoding.StyleEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { JsonNode node = jp.getCodec().readTree(jp); if (node != null) { String value = node.asText(); return getStyleEnum(value); } return null; } private Encoding.StyleEnum getStyleEnum(String value) { return Arrays.stream( Encoding.StyleEnum.values()) .filter(i -> i.toString().equals(value)) .findFirst() .orElseThrow(() -> new RuntimeException( String.format("Can not deserialize value of type Encoding.StyleEnum from String \"%s\": value not one of declared Enum instance names: %s", value, Arrays.stream(Encoding.StyleEnum.values()).map(Encoding.StyleEnum::toString).collect(Collectors.joining(", ", "[", "]"))))); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/HeaderStyleEnumDeserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.models.headers.Header; import java.io.IOException; import java.util.Arrays; import java.util.stream.Collectors; public class HeaderStyleEnumDeserializer extends JsonDeserializer { @Override public Header.StyleEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { JsonNode node = jp.getCodec().readTree(jp); if (node != null) { String value = node.asText(); return getStyleEnum(value); } return null; } private Header.StyleEnum getStyleEnum(String value) { return Arrays.stream( Header.StyleEnum.values()) .filter(i -> i.toString().equals(value)) .findFirst() .orElseThrow(() -> new RuntimeException( String.format("Can not deserialize value of type Header.StyleEnum from String \"%s\": value not one of declared Enum instance names: %s", value, Arrays.stream(Header.StyleEnum.values()).map(Header.StyleEnum::toString).collect(Collectors.joining(", ", "[", "]"))))); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Json { private static final class ObjectMapperHolder { private static final ObjectMapper MAPPER = ObjectMapperFactory.createJson(); } private static final Logger LOGGER = LoggerFactory.getLogger(Json.class); public static ObjectMapper mapper() { return ObjectMapperHolder.MAPPER; } public static ObjectWriter pretty() { return mapper().writer(new DefaultPrettyPrinter()); } public static String pretty(Object o) { try { return pretty().writeValueAsString(o); } catch (Exception e) { PrettyPrintHelper.emitError(LOGGER, "Error serializing object to JSON", e); return null; } } public static void prettyPrint(Object o) { try { String prettyString = pretty().writeValueAsString(o).replace("\r", ""); PrettyPrintHelper.emit(LOGGER, prettyString); } catch (Exception e) { PrettyPrintHelper.emitError(LOGGER, "Error pretty-printing JSON", e); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json31.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import io.swagger.v3.oas.models.media.Schema; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; public class Json31 { private static final class ObjectMapperHolder { private static final ObjectMapper MAPPER = ObjectMapperFactory.createJson31(); } private static final class ConverterMapperHolder { private static final ObjectMapper MAPPER = ObjectMapperFactory.createJsonConverter(); } private static final Logger LOGGER = LoggerFactory.getLogger(Json31.class); public static ObjectMapper mapper() { return ObjectMapperHolder.MAPPER; } public static ObjectMapper converterMapper() { return ConverterMapperHolder.MAPPER; } public static ObjectWriter pretty() { return mapper().writer(new DefaultPrettyPrinter()); } public static String pretty(Object o) { try { return pretty().writeValueAsString(o); } catch (Exception e) { PrettyPrintHelper.emitError(LOGGER, "Error serializing object to JSON (3.1)", e); return null; } } public static void prettyPrint(Object o) { try { String prettyString = pretty().writeValueAsString(o).replace("\r", ""); PrettyPrintHelper.emit(LOGGER, prettyString); } catch (Exception e) { PrettyPrintHelper.emitError(LOGGER, "Error pretty-printing JSON (3.1)", e); } } public static Map jsonSchemaAsMap(String jsonSchema) { try { return mapper().readValue(jsonSchema, Map.class); } catch (JsonProcessingException e) { LOGGER.error("Exception converting jsonSchema to Map", e); return null; } } public static Map jsonSchemaAsMap(Schema schema) { try { return mapper().readValue(mapper().writeValueAsString(schema), Map.class); } catch (JsonProcessingException e) { LOGGER.error("Exception converting jsonSchema to Map", e); return null; } } public static Map jsonSchemaAsMap(JsonNode schema) { try { return mapper().readValue(mapper().writeValueAsString(schema), Map.class); } catch (JsonProcessingException e) { LOGGER.error("Exception converting jsonSchema to Map", e); return null; } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/KotlinDetector.java ================================================ package io.swagger.v3.core.util; import java.lang.annotation.Annotation; public class KotlinDetector { private static final Boolean kotlinAvailable; private static final Class kotlinDeprecated; static { kotlinAvailable = loadByClassOrNull("kotlin.Metadata") != null; kotlinDeprecated = loadByClassOrNull("kotlin.Deprecated"); } private static Class loadByClassOrNull(String className) { try { return (Class) ReflectionUtils.loadClassByName(className); } catch (ClassNotFoundException ex) { return null; } } public static boolean isKotlinPresent() { return kotlinAvailable; } public static Class getKotlinDeprecated() { return kotlinDeprecated; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Model31Deserializer.java ================================================ package io.swagger.v3.core.util; public class Model31Deserializer extends ModelDeserializer { public Model31Deserializer() {this.openapi31 = true;} } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ModelDeserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import io.swagger.v3.oas.models.media.ArbitrarySchema; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.BooleanSchema; import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.DateSchema; import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.EmailSchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.JsonSchema; import io.swagger.v3.oas.models.media.MapSchema; import io.swagger.v3.oas.models.media.NumberSchema; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.PasswordSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.media.UUIDSchema; import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; public class ModelDeserializer extends JsonDeserializer { static Boolean useArbitrarySchema = false; static { if (System.getenv(Schema.USE_ARBITRARY_SCHEMA_PROPERTY) != null) { useArbitrarySchema = Boolean.parseBoolean(System.getenv(Schema.USE_ARBITRARY_SCHEMA_PROPERTY)); } else if (System.getProperty(Schema.USE_ARBITRARY_SCHEMA_PROPERTY) != null) { useArbitrarySchema = Boolean.parseBoolean(System.getProperty(Schema.USE_ARBITRARY_SCHEMA_PROPERTY)); } } protected boolean openapi31 = false; @Override public Schema deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { JsonNode node = jp.getCodec().readTree(jp); Schema schema = null; if (openapi31) { schema = deserializeJsonSchema(node); return schema; } if (node.isBoolean()) { return new Schema().booleanSchemaValue(node.booleanValue()); } List composed = Arrays.asList("allOf", "anyOf", "oneOf"); for (String field: composed) { if (node.get(field) != null) { return Json.mapper().convertValue(node, ComposedSchema.class); } } JsonNode type = node.get("type"); String format = node.get("format") == null ? "" : node.get("format").textValue(); if (type != null && "array".equals(((TextNode) type).textValue())) { schema = Json.mapper().convertValue(node, ArraySchema.class); } else if (type != null) { if (type.textValue().equals("integer")) { schema = Json.mapper().convertValue(node, IntegerSchema.class); if (StringUtils.isBlank(format)) { schema.setFormat(null); } } else if (type.textValue().equals("number")) { schema = Json.mapper().convertValue(node, NumberSchema.class); } else if (type.textValue().equals("boolean")) { schema = Json.mapper().convertValue(node, BooleanSchema.class); } else if (type.textValue().equals("string")) { if ("date".equals(format)) { schema = Json.mapper().convertValue(node, DateSchema.class); } else if ("date-time".equals(format)) { schema = Json.mapper().convertValue(node, DateTimeSchema.class); } else if ("email".equals(format)) { schema = Json.mapper().convertValue(node, EmailSchema.class); } else if ("password".equals(format)) { schema = Json.mapper().convertValue(node, PasswordSchema.class); } else if ("uuid".equals(format)) { schema = Json.mapper().convertValue(node, UUIDSchema.class); } else { schema = Json.mapper().convertValue(node, StringSchema.class); } } else if (type.textValue().equals("object")) { schema = deserializeArbitraryOrObjectSchema(node, true); } } else if (node.get("$ref") != null) { schema = new Schema().$ref(node.get("$ref").asText()); } else { schema = deserializeArbitraryOrObjectSchema(node, false); } return schema; } private Schema deserializeArbitraryOrObjectSchema(JsonNode node, boolean alwaysObject) { JsonNode additionalProperties = node.get("additionalProperties"); Schema schema = null; if (additionalProperties != null) { if (additionalProperties.isBoolean()) { Boolean additionalPropsBoolean = Json.mapper().convertValue(additionalProperties, Boolean.class); ((ObjectNode)node).remove("additionalProperties"); if (additionalPropsBoolean) { schema = Json.mapper().convertValue(node, MapSchema.class); } else { schema = Json.mapper().convertValue(node, ObjectSchema.class); } schema.setAdditionalProperties(additionalPropsBoolean); } else { Schema innerSchema = Json.mapper().convertValue(additionalProperties, Schema.class); ((ObjectNode)node).remove("additionalProperties"); MapSchema ms = Json.mapper().convertValue(node, MapSchema.class); ms.setAdditionalProperties(innerSchema); schema = ms; } } else { if (!Boolean.TRUE.equals(useArbitrarySchema) || alwaysObject) { schema = Json.mapper().convertValue(node, ObjectSchema.class); } else { schema = Json.mapper().convertValue(node, ArbitrarySchema.class); } } if (schema != null) { schema.jsonSchema(Json31.jsonSchemaAsMap(node)); } return schema; } private Schema deserializeJsonSchema(JsonNode node) { if (node.isBoolean()) { return new Schema().booleanSchemaValue(node.booleanValue()); } JsonNode additionalProperties = node.get("additionalProperties"); JsonNode type = node.get("type"); Schema schema = null; if (type != null || additionalProperties != null) { if (type != null) { ((ObjectNode)node).remove("type"); } if (additionalProperties != null) { ((ObjectNode)node).remove("additionalProperties"); } schema = Json31.mapper().convertValue(node, JsonSchema.class); if (type instanceof TextNode) { schema.types(new LinkedHashSet<>(Arrays.asList(type.textValue()))); } else if (type instanceof ArrayNode){ Set types = new LinkedHashSet<>(); ((ArrayNode)type).elements().forEachRemaining( n -> { types.add(n.textValue()); }); schema.types(types); } if (additionalProperties != null) { try { if (additionalProperties.isBoolean()) { schema.setAdditionalProperties(additionalProperties.booleanValue()); } else { Schema innerSchema = deserializeJsonSchema(additionalProperties); schema.setAdditionalProperties(innerSchema); } } catch (Exception e) { Boolean additionalPropsBoolean = Json31.mapper().convertValue(additionalProperties, Boolean.class); schema.setAdditionalProperties(additionalPropsBoolean); } } } else { schema = Json31.mapper().convertValue(node, JsonSchema.class); } return schema; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ObjectMapperFactory.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.swagger.v3.core.jackson.ExampleSerializer; import io.swagger.v3.core.jackson.Schema31Serializer; import io.swagger.v3.core.jackson.MediaTypeSerializer; import io.swagger.v3.core.jackson.SchemaSerializer; import io.swagger.v3.core.jackson.mixin.Components31Mixin; import io.swagger.v3.core.jackson.mixin.ComponentsMixin; import io.swagger.v3.core.jackson.mixin.DateSchemaMixin; import io.swagger.v3.core.jackson.mixin.Discriminator31Mixin; import io.swagger.v3.core.jackson.mixin.DiscriminatorMixin; import io.swagger.v3.core.jackson.mixin.ExampleMixin; import io.swagger.v3.core.jackson.mixin.ExtensionsMixin; import io.swagger.v3.core.jackson.mixin.InfoMixin; import io.swagger.v3.core.jackson.mixin.LicenseMixin; import io.swagger.v3.core.jackson.mixin.MediaTypeMixin; import io.swagger.v3.core.jackson.mixin.OpenAPI31Mixin; import io.swagger.v3.core.jackson.mixin.OpenAPIMixin; import io.swagger.v3.core.jackson.mixin.OperationMixin; import io.swagger.v3.core.jackson.mixin.Schema31Mixin; import io.swagger.v3.core.jackson.mixin.SchemaConverterMixin; import io.swagger.v3.core.jackson.mixin.SchemaMixin; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.ExternalDocumentation; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.links.LinkParameter; import io.swagger.v3.oas.models.media.DateSchema; import io.swagger.v3.oas.models.media.Discriminator; import io.swagger.v3.oas.models.media.Encoding; import io.swagger.v3.oas.models.media.EncodingProperty; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.XML; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.OAuthFlow; import io.swagger.v3.oas.models.security.OAuthFlows; import io.swagger.v3.oas.models.security.Scopes; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.oas.models.servers.ServerVariable; import io.swagger.v3.oas.models.servers.ServerVariables; import io.swagger.v3.oas.models.tags.Tag; import java.util.LinkedHashMap; import java.util.Map; public class ObjectMapperFactory { public static ObjectMapper createJson(JsonFactory jsonFactory) { return create(jsonFactory, false); } public static ObjectMapper createJson() { return create(null, false); } public static ObjectMapper createYaml(YAMLFactory yamlFactory) { return create(yamlFactory, false); } public static ObjectMapper createYaml() { return createYaml(false); } public static ObjectMapper createYaml(boolean openapi31) { YAMLFactory factory = new YAMLFactory(); factory.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER); factory.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES); factory.enable(YAMLGenerator.Feature.SPLIT_LINES); factory.enable(YAMLGenerator.Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS); return create(factory, openapi31); } public static ObjectMapper createJson31(JsonFactory jsonFactory) { return create(jsonFactory, true); } public static ObjectMapper createJson31() { return create(null, true); } public static ObjectMapper createYaml31(YAMLFactory yamlFactory) { return create(yamlFactory, true); } public static ObjectMapper createYaml31() { return createYaml(true); } public static ObjectMapper create(JsonFactory jsonFactory, boolean openapi31) { ObjectMapper mapper = jsonFactory == null ? new ObjectMapper() : new ObjectMapper(jsonFactory); if (!openapi31) { // handle ref schema serialization skipping all other props mapper.registerModule(new SimpleModule() { @Override public void setupModule(SetupContext context) { super.setupModule(context); context.addBeanSerializerModifier(new BeanSerializerModifier() { @Override public JsonSerializer modifySerializer( SerializationConfig config, BeanDescription desc, JsonSerializer serializer) { if (Schema.class.isAssignableFrom(desc.getBeanClass())) { return new SchemaSerializer((JsonSerializer) serializer); } else if (MediaType.class.isAssignableFrom(desc.getBeanClass())) { return new MediaTypeSerializer((JsonSerializer) serializer); } else if (Example.class.isAssignableFrom(desc.getBeanClass())) { return new ExampleSerializer((JsonSerializer) serializer); } return serializer; } }); } }); } else { mapper.registerModule(new SimpleModule() { @Override public void setupModule(SetupContext context) { super.setupModule(context); context.addBeanSerializerModifier(new BeanSerializerModifier() { @Override public JsonSerializer modifySerializer( SerializationConfig config, BeanDescription desc, JsonSerializer serializer) { if (Schema.class.isAssignableFrom(desc.getBeanClass())) { return new Schema31Serializer((JsonSerializer) serializer); } else if (MediaType.class.isAssignableFrom(desc.getBeanClass())) { return new MediaTypeSerializer((JsonSerializer) serializer); } else if (Example.class.isAssignableFrom(desc.getBeanClass())) { return new ExampleSerializer((JsonSerializer) serializer); } return serializer; } }); } }); } if (!openapi31) { Module deserializerModule = new DeserializationModule(); mapper.registerModule(deserializerModule); } else { Module deserializerModule = new DeserializationModule31(); mapper.registerModule(deserializerModule); } mapper.registerModule(new JavaTimeModule()); Map, Class> sourceMixins = new LinkedHashMap<>(); sourceMixins.put(ApiResponses.class, ExtensionsMixin.class); sourceMixins.put(Contact.class, ExtensionsMixin.class); sourceMixins.put(Encoding.class, ExtensionsMixin.class); sourceMixins.put(EncodingProperty.class, ExtensionsMixin.class); sourceMixins.put(Example.class, ExampleMixin.class); sourceMixins.put(ExternalDocumentation.class, ExtensionsMixin.class); sourceMixins.put(Link.class, ExtensionsMixin.class); sourceMixins.put(LinkParameter.class, ExtensionsMixin.class); sourceMixins.put(MediaType.class, MediaTypeMixin.class); sourceMixins.put(OAuthFlow.class, ExtensionsMixin.class); sourceMixins.put(OAuthFlows.class, ExtensionsMixin.class); sourceMixins.put(Operation.class, OperationMixin.class); sourceMixins.put(PathItem.class, ExtensionsMixin.class); sourceMixins.put(Paths.class, ExtensionsMixin.class); sourceMixins.put(Scopes.class, ExtensionsMixin.class); sourceMixins.put(Server.class, ExtensionsMixin.class); sourceMixins.put(ServerVariable.class, ExtensionsMixin.class); sourceMixins.put(ServerVariables.class, ExtensionsMixin.class); sourceMixins.put(Tag.class, ExtensionsMixin.class); sourceMixins.put(XML.class, ExtensionsMixin.class); sourceMixins.put(ApiResponse.class, ExtensionsMixin.class); sourceMixins.put(Parameter.class, ExtensionsMixin.class); sourceMixins.put(RequestBody.class, ExtensionsMixin.class); sourceMixins.put(Header.class, ExtensionsMixin.class); sourceMixins.put(SecurityScheme.class, ExtensionsMixin.class); sourceMixins.put(Callback.class, ExtensionsMixin.class); if (!openapi31) { sourceMixins.put(Schema.class, SchemaMixin.class); sourceMixins.put(DateSchema.class, DateSchemaMixin.class); sourceMixins.put(Components.class, ComponentsMixin.class); sourceMixins.put(Info.class, InfoMixin.class); sourceMixins.put(License.class, LicenseMixin.class); sourceMixins.put(OpenAPI.class, OpenAPIMixin.class); sourceMixins.put(Discriminator.class, DiscriminatorMixin.class); } else { sourceMixins.put(Info.class, ExtensionsMixin.class); sourceMixins.put(Schema.class, Schema31Mixin.class); sourceMixins.put(Components.class, Components31Mixin.class); sourceMixins.put(OpenAPI.class, OpenAPI31Mixin.class); sourceMixins.put(DateSchema.class, DateSchemaMixin.class); sourceMixins.put(Discriminator.class, Discriminator31Mixin.class); } mapper.setMixIns(sourceMixins); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false); mapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN, true); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper; } public static ObjectMapper createJsonConverter() { ObjectMapper mapper = new ObjectMapper(); Module deserializerModule = new DeserializationModule(); mapper.registerModule(deserializerModule); mapper.registerModule(new JavaTimeModule()); Map, Class> sourceMixins = new LinkedHashMap<>(); sourceMixins.put(ApiResponses.class, ExtensionsMixin.class); sourceMixins.put(ApiResponse.class, ExtensionsMixin.class); sourceMixins.put(Callback.class, ExtensionsMixin.class); sourceMixins.put(Components.class, ComponentsMixin.class); sourceMixins.put(Contact.class, ExtensionsMixin.class); sourceMixins.put(Encoding.class, ExtensionsMixin.class); sourceMixins.put(EncodingProperty.class, ExtensionsMixin.class); sourceMixins.put(Example.class, ExampleMixin.class); sourceMixins.put(ExternalDocumentation.class, ExtensionsMixin.class); sourceMixins.put(Header.class, ExtensionsMixin.class); sourceMixins.put(Info.class, ExtensionsMixin.class); sourceMixins.put(License.class, ExtensionsMixin.class); sourceMixins.put(Link.class, ExtensionsMixin.class); sourceMixins.put(LinkParameter.class, ExtensionsMixin.class); sourceMixins.put(MediaType.class, MediaTypeMixin.class); sourceMixins.put(OAuthFlow.class, ExtensionsMixin.class); sourceMixins.put(OAuthFlows.class, ExtensionsMixin.class); sourceMixins.put(OpenAPI.class, OpenAPIMixin.class); sourceMixins.put(Operation.class, OperationMixin.class); sourceMixins.put(Parameter.class, ExtensionsMixin.class); sourceMixins.put(PathItem.class, ExtensionsMixin.class); sourceMixins.put(Paths.class, ExtensionsMixin.class); sourceMixins.put(RequestBody.class, ExtensionsMixin.class); sourceMixins.put(Scopes.class, ExtensionsMixin.class); sourceMixins.put(SecurityScheme.class, ExtensionsMixin.class); sourceMixins.put(Server.class, ExtensionsMixin.class); sourceMixins.put(ServerVariable.class, ExtensionsMixin.class); sourceMixins.put(ServerVariables.class, ExtensionsMixin.class); sourceMixins.put(Tag.class, ExtensionsMixin.class); sourceMixins.put(XML.class, ExtensionsMixin.class); sourceMixins.put(Schema.class, SchemaConverterMixin.class); mapper.setMixIns(sourceMixins); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false); mapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN, true); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper; } public static ObjectMapper buildStrictGenericObjectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false); try { mapper.configure(DeserializationFeature.valueOf("FAIL_ON_TRAILING_TOKENS"), true); } catch (Throwable e) { // add only if supported by Jackson version 2.9+ } mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/OpenAPI30To31.java ================================================ package io.swagger.v3.core.util; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.SpecVersion; import java.util.Map; import java.util.Set; public class OpenAPI30To31 { public void process(OpenAPI openAPI) { openAPI.openapi("3.1.0") .jsonSchemaDialect("https://spec.openapis.org/oas/3.1/dialect/base") .specVersion(SpecVersion.V31); removeReservedExtensionsName(openAPI.getExtensions()); if (openAPI.getInfo() != null) { removeReservedExtensionsName(openAPI.getInfo().getExtensions()); } if (openAPI.getPaths() != null) { removeReservedExtensionsName(openAPI.getPaths().getExtensions()); } if (openAPI.getComponents() != null) { removeReservedExtensionsName(openAPI.getComponents().getExtensions()); } } private void removeReservedExtensionsName(Map extensions) { if (extensions == null || extensions.isEmpty()) { return; } final Set keys = extensions.keySet(); for (String key : keys) { if (key.startsWith("x-oas-") || key.startsWith("x-oai-")) { extensions.remove(key); } } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/OpenAPI31Deserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.SpecVersion; import java.io.IOException; public class OpenAPI31Deserializer extends StdDeserializer implements ResolvableDeserializer { private final JsonDeserializer defaultDeserializer; public OpenAPI31Deserializer(JsonDeserializer defaultDeserializer) { super(OpenAPI.class); this.defaultDeserializer = defaultDeserializer; } @Override public OpenAPI deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { OpenAPI openAPI = (OpenAPI) defaultDeserializer.deserialize(jp, ctxt); openAPI.setSpecVersion(SpecVersion.V31); return openAPI; } @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException { ((ResolvableDeserializer) defaultDeserializer).resolve(ctxt); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/OpenAPISchema2JsonSchema.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.models.SpecVersion; import io.swagger.v3.oas.models.media.Schema; import java.util.LinkedHashSet; import java.util.Map; public class OpenAPISchema2JsonSchema { protected final ObjectMapper converterMapper = Json31.converterMapper(); public void process(Schema schema) { schema.specVersion(SpecVersion.V31); Map jsonSchema = converterMapper.convertValue(schema, Map.class); // handle nullable if (schema.getType() != null || Boolean.TRUE.equals(schema.getNullable())) { schema.types(new LinkedHashSet<>()); } if (schema.getType() != null) { schema.getTypes().add(schema.getType()); } schema.type(null); if (Boolean.TRUE.equals(schema.getNullable())) { schema.nullable(null); schema.getTypes().add("null"); } if (schema.getMinimum() != null && Boolean.TRUE.equals(schema.getExclusiveMinimum())) { schema.setExclusiveMinimumValue(schema.getMinimum()); } if (schema.getMaximum() != null && Boolean.TRUE.equals(schema.getExclusiveMaximum())) { schema.setExclusiveMaximumValue(schema.getMaximum()); } schema.jsonSchema(jsonSchema); if (schema.getAdditionalProperties() instanceof Schema) { process((Schema) schema.getAdditionalProperties()); } if (schema.getAllOf() != null) { schema.getAllOf().forEach(this::process); } if (schema.getAnyOf() != null) { schema.getAnyOf().forEach(this::process); } if (schema.getOneOf() != null) { schema.getOneOf().forEach(this::process); } if (schema.getProperties() != null) { schema.getProperties().values().forEach(this::process); } if (schema.getItems() != null) { process(schema.getItems()); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Parameter31Deserializer.java ================================================ package io.swagger.v3.core.util; public class Parameter31Deserializer extends ParameterDeserializer { public Parameter31Deserializer() { this.openapi31 = true; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterDeserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import io.swagger.v3.oas.models.parameters.CookieParameter; import io.swagger.v3.oas.models.parameters.HeaderParameter; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.PathParameter; import io.swagger.v3.oas.models.parameters.QueryParameter; import java.io.IOException; public class ParameterDeserializer extends JsonDeserializer { protected boolean openapi31; @Override public Parameter deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { Parameter result = null; JsonNode node = jp.getCodec().readTree(jp); JsonNode sub = node.get("$ref"); JsonNode inNode = node.get("in"); JsonNode desc = node.get("description"); if (sub != null) { result = new Parameter().$ref(sub.asText()); if (desc != null && openapi31) { result.description(desc.asText()); } } else if (inNode != null) { String in = inNode.asText(); ObjectReader reader = null; ObjectMapper mapper = null; if (openapi31) { mapper = Json31.mapper(); } else { mapper = Json.mapper(); } if ("query".equals(in)) { reader = mapper.readerFor(QueryParameter.class); } else if ("header".equals(in)) { reader = mapper.readerFor(HeaderParameter.class); } else if ("path".equals(in)) { reader = mapper.readerFor(PathParameter.class); } else if ("cookie".equals(in)) { reader = mapper.readerFor(CookieParameter.class); } if (reader != null) { result = reader.with(DeserializationFeature.READ_ENUMS_USING_TO_STRING).readValue(node); } } return result; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.annotation.JsonView; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; public class ParameterProcessor { static Logger LOGGER = LoggerFactory.getLogger(ParameterProcessor.class); public static Parameter applyAnnotations(Parameter parameter, Type type, List annotations, Components components, String[] classTypes, String[] methodTypes, JsonView jsonViewAnnotation) { return applyAnnotations(parameter, type, annotations, components, classTypes, methodTypes, jsonViewAnnotation, false); } public static Parameter applyAnnotations( Parameter parameter, Type type, List annotations, Components components, String[] classTypes, String[] methodTypes, JsonView jsonViewAnnotation, boolean openapi31) { return applyAnnotations(parameter, type, annotations, components, classTypes, methodTypes, jsonViewAnnotation, openapi31, null); } public static Parameter applyAnnotations( Parameter parameter, Type type, List annotations, Components components, String[] classTypes, String[] methodTypes, JsonView jsonViewAnnotation, boolean openapi31, Schema.SchemaResolution schemaResolution) { Configuration configuration = new Configuration(); configuration.setOpenAPI31(openapi31); configuration.setSchemaResolution(schemaResolution); return applyAnnotations(parameter, type, annotations, components, classTypes, methodTypes, jsonViewAnnotation, configuration); } public static Parameter applyAnnotations( Parameter parameter, Type type, List annotations, Components components, String[] classTypes, String[] methodTypes, JsonView jsonViewAnnotation, Configuration configuration) { boolean openapi31 = configuration != null && configuration.isOpenAPI31() != null && configuration.isOpenAPI31(); Schema.SchemaResolution schemaResolution = configuration.getSchemaResolution();; final AnnotationsHelper helper = new AnnotationsHelper(annotations, type); if (helper.isContext()) { return null; } if (parameter == null) { // consider it to be body param parameter = new Parameter(); } // first handle schema List reworkedAnnotations = new ArrayList<>(annotations); Annotation paramSchemaOrArrayAnnotation = getParamSchemaAnnotation(annotations); if (paramSchemaOrArrayAnnotation != null) { reworkedAnnotations.add(paramSchemaOrArrayAnnotation); } io.swagger.v3.oas.annotations.media.Schema ctxSchema = AnnotationsUtils.getSchemaAnnotation(annotations.toArray(new Annotation[0])); io.swagger.v3.oas.annotations.media.ArraySchema ctxArraySchema = AnnotationsUtils.getArraySchemaAnnotation(annotations.toArray(new Annotation[0])); Annotation[] ctxAnnotation31 = null; if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution)) { List ctxAnnotations31List = new ArrayList<>(); if (annotations != null) { for (Annotation a : annotations) { if ( !(a instanceof io.swagger.v3.oas.annotations.media.Schema) && !(a instanceof io.swagger.v3.oas.annotations.media.ArraySchema)) { ctxAnnotations31List.add(a); } } ctxAnnotation31 = ctxAnnotations31List.toArray(new Annotation[ctxAnnotations31List.size()]); } } AnnotatedType annotatedType = new AnnotatedType() .type(type) .resolveAsRef(true) .skipOverride(true) .jsonViewAnnotation(jsonViewAnnotation); if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution)) { annotatedType.ctxAnnotations(ctxAnnotation31); } else { annotatedType.ctxAnnotations(reworkedAnnotations.toArray(new Annotation[reworkedAnnotations.size()])); } final ResolvedSchema resolvedSchema = ModelConverters.getInstance(configuration).resolveAsResolvedSchema(annotatedType); if (resolvedSchema.schema != null) { Schema resSchema = AnnotationsUtils.clone(resolvedSchema.schema, openapi31); Schema ctxSchemaObject = null; if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution)) { Optional reResolvedSchema = AnnotationsUtils.getSchemaFromAnnotation(ctxSchema, annotatedType.getComponents(), null, openapi31, null, schemaResolution, null); if (reResolvedSchema.isPresent()) { ctxSchemaObject = reResolvedSchema.get(); } reResolvedSchema = AnnotationsUtils.getArraySchema(ctxArraySchema, annotatedType.getComponents(), null, openapi31, ctxSchemaObject); if (reResolvedSchema.isPresent()) { ctxSchemaObject = reResolvedSchema.get(); } } if (Schema.SchemaResolution.ALL_OF.equals(schemaResolution) && ctxSchemaObject != null) { resSchema = new Schema() .addAllOfItem(ctxSchemaObject) .addAllOfItem(resolvedSchema.schema); } else if (Schema.SchemaResolution.ALL_OF_REF.equals(schemaResolution) && ctxSchemaObject != null) { resSchema = ctxSchemaObject .addAllOfItem(resolvedSchema.schema); } parameter.setSchema(resSchema); } resolvedSchema.referencedSchemas.forEach(components::addSchemas); // handle first FormParam as it affects Explode resolving for (Annotation annotation : annotations) { if (annotation.annotationType().getName().equals("javax.ws.rs.FormParam")) { try { String name = (String) annotation.annotationType().getMethod("value").invoke(annotation); if (StringUtils.isNotBlank(name)) { parameter.setName(name); } } catch (Exception e) { } // set temporarily to "form" to inform caller that we need to further process along other form parameters parameter.setIn("form"); } else if (annotation.annotationType().getName().endsWith("FormDataParam")) { try { String name = (String) annotation.annotationType().getMethod("value").invoke(annotation); if (StringUtils.isNotBlank(name)) { parameter.setName(name); } } catch (Exception e) { } // set temporarily to "form" to inform caller that we need to further process along other form parameters parameter.setIn("form"); } } for (Annotation annotation : annotations) { if (annotation instanceof io.swagger.v3.oas.annotations.Parameter) { io.swagger.v3.oas.annotations.Parameter p = (io.swagger.v3.oas.annotations.Parameter) annotation; if (p.hidden()) { return null; } if (StringUtils.isNotBlank(p.ref())) { parameter = new Parameter().$ref(p.ref()); return parameter; } if (StringUtils.isNotBlank(p.description())) { parameter.setDescription(p.description()); } if (StringUtils.isNotBlank(p.name())) { parameter.setName(p.name()); } if (StringUtils.isNotBlank(p.in().toString())) { parameter.setIn(p.in().toString()); } if (StringUtils.isNotBlank(p.example())) { try { parameter.setExample(Json.mapper().readTree(p.example())); } catch (IOException e) { parameter.setExample(p.example()); } } if (p.deprecated()) { parameter.setDeprecated(p.deprecated()); } if (p.required()) { parameter.setRequired(p.required()); } if (p.allowEmptyValue()) { parameter.setAllowEmptyValue(p.allowEmptyValue()); } if (p.allowReserved()) { parameter.setAllowReserved(p.allowReserved()); } Map exampleMap = new LinkedHashMap<>(); if (p.examples().length == 1 && StringUtils.isBlank(p.examples()[0].name())) { Optional exampleOptional = AnnotationsUtils.getExample(p.examples()[0], true); if (exampleOptional.isPresent()) { parameter.setExample(exampleOptional.get()); } } else { for (ExampleObject exampleObject : p.examples()) { AnnotationsUtils.getExample(exampleObject).ifPresent(example -> exampleMap.put(exampleObject.name(), example)); } } if (exampleMap.size() > 0) { parameter.setExamples(exampleMap); } if (p.extensions().length > 0) { Map extensionMap = AnnotationsUtils.getExtensions(openapi31, p.extensions()); if (extensionMap != null && ! extensionMap.isEmpty()) { extensionMap.forEach(parameter::addExtension); } } Optional content = AnnotationsUtils.getContent(p.content(), classTypes, methodTypes, parameter.getSchema(), null, jsonViewAnnotation); if (content.isPresent()) { parameter.setContent(content.get()); parameter.setSchema(null); } setParameterStyle(parameter, p); setParameterExplode(parameter, p); } else if (annotation.annotationType().getName().equals("javax.ws.rs.PathParam")) { try { String name = (String) annotation.annotationType().getMethod("value").invoke(annotation); if (StringUtils.isNotBlank(name)) { parameter.setName(name); } } catch (Exception e) { } } else if (annotation.annotationType().getName().equals("javax.validation.constraints.Size")) { try { if (parameter.getSchema() == null) { parameter.setSchema(new ArraySchema()); } if (isArraySchema(parameter.getSchema())) { Schema as = parameter.getSchema(); Integer min = (Integer) annotation.annotationType().getMethod("min").invoke(annotation); if (min != null) { as.setMinItems(min); } Integer max = (Integer) annotation.annotationType().getMethod("max").invoke(annotation); if (max != null) { as.setMaxItems(max); } } } catch (Exception e) { LOGGER.error("failed on " + annotation.annotationType().getName(), e); } } else if (ModelResolver.NOT_NULL_ANNOTATIONS.contains(annotation.annotationType().getSimpleName())) { parameter.setRequired(true); } } final String defaultValue = helper.getDefaultValue(); Schema paramSchema = parameter.getSchema(); if (paramSchema == null) { if (parameter.getContent() != null && !parameter.getContent().values().isEmpty()) { paramSchema = parameter.getContent().values().iterator().next().getSchema(); } } if (paramSchema != null) { if (isArraySchema(paramSchema)) { if (defaultValue != null) { paramSchema.getItems().setDefault(defaultValue); } } else { if (defaultValue != null) { paramSchema.setDefault(defaultValue); } } } return parameter; } public static boolean isArraySchema(Schema schema) { return "array".equals(schema.getType()) || (schema.getTypes() != null && schema.getTypes().contains("array")); } public static void setParameterExplode(Parameter parameter, io.swagger.v3.oas.annotations.Parameter p) { if (isExplodable(p, parameter)) { if (Explode.TRUE.equals(p.explode())) { parameter.setExplode(Boolean.TRUE); } else if (Explode.FALSE.equals(p.explode())) { parameter.setExplode(Boolean.FALSE); } } } private static boolean isExplodable(io.swagger.v3.oas.annotations.Parameter p, Parameter parameter) { io.swagger.v3.oas.annotations.media.Schema schema = AnnotationsUtils.hasArrayAnnotation(p.array()) ? p.array().schema() : p.schema(); boolean explode = true; if (schema != null) { Class implementation = schema.implementation(); if (implementation == Void.class) { if (!schema.type().equals("object") && !schema.type().equals("array") && !schema.type().isEmpty()) { explode = false; } if (schema.types().length != 0 && (!Arrays.asList(schema.types()).contains("array") && !Arrays.asList(schema.types()).contains("object"))) { explode = false; } } } return explode; } public static void setParameterStyle(Parameter parameter, io.swagger.v3.oas.annotations.Parameter p) { if (StringUtils.isNotBlank(p.style().toString())) { parameter.setStyle(Parameter.StyleEnum.valueOf(p.style().toString().toUpperCase())); } } public static Annotation getParamSchemaAnnotation(List annotations) { if (annotations == null) { return null; } io.swagger.v3.oas.annotations.media.Schema rootSchema = null; io.swagger.v3.oas.annotations.media.ArraySchema rootArraySchema = null; io.swagger.v3.oas.annotations.media.Schema contentSchema = null; io.swagger.v3.oas.annotations.media.Schema paramSchema = null; io.swagger.v3.oas.annotations.media.ArraySchema paramArraySchema = null; for (Annotation annotation : annotations) { if (annotation instanceof io.swagger.v3.oas.annotations.media.Schema) { rootSchema = (io.swagger.v3.oas.annotations.media.Schema) annotation; } else if (annotation instanceof io.swagger.v3.oas.annotations.media.ArraySchema) { rootArraySchema = (io.swagger.v3.oas.annotations.media.ArraySchema) annotation; } else if (annotation instanceof io.swagger.v3.oas.annotations.Parameter) { io.swagger.v3.oas.annotations.Parameter paramAnnotation = (io.swagger.v3.oas.annotations.Parameter) annotation; if (paramAnnotation.content().length > 0) { if (AnnotationsUtils.hasSchemaAnnotation(paramAnnotation.content()[0].schema())) { contentSchema = paramAnnotation.content()[0].schema(); } } if (AnnotationsUtils.hasSchemaAnnotation(paramAnnotation.schema())) { paramSchema = paramAnnotation.schema(); } if (AnnotationsUtils.hasArrayAnnotation(paramAnnotation.array())) { paramArraySchema = paramAnnotation.array(); } } } if (rootSchema != null || rootArraySchema != null) { return null; } if (contentSchema != null) { return contentSchema; } if (paramSchema != null) { return paramSchema; } if (paramArraySchema != null) { return paramArraySchema; } return null; } public static Type getParameterType(io.swagger.v3.oas.annotations.Parameter paramAnnotation) { return getParameterType(paramAnnotation, false); } public static Type getParameterType(io.swagger.v3.oas.annotations.Parameter paramAnnotation, boolean nullIfNotFound) { if (paramAnnotation == null) { return null; } io.swagger.v3.oas.annotations.media.Schema contentSchema = null; io.swagger.v3.oas.annotations.media.Schema paramSchema = null; io.swagger.v3.oas.annotations.media.ArraySchema paramArraySchema = null; if (paramAnnotation.content().length > 0) { if (AnnotationsUtils.hasSchemaAnnotation(paramAnnotation.content()[0].schema())) { contentSchema = paramAnnotation.content()[0].schema(); } } if (AnnotationsUtils.hasSchemaAnnotation(paramAnnotation.schema())) { paramSchema = paramAnnotation.schema(); } if (AnnotationsUtils.hasArrayAnnotation(paramAnnotation.array())) { paramArraySchema = paramAnnotation.array(); } if (contentSchema != null) { return AnnotationsUtils.getSchemaType(contentSchema, nullIfNotFound); } if (paramSchema != null) { return AnnotationsUtils.getSchemaType(paramSchema, nullIfNotFound); } if (paramArraySchema != null) { return AnnotationsUtils.getSchemaType(paramArraySchema.schema(), nullIfNotFound); } if (nullIfNotFound) { return null; } return String.class; } public static final String MEDIA_TYPE = "*/*"; /** * The AnnotationsHelper class defines helper methods for * accessing supported parameter annotations. */ private static class AnnotationsHelper { private boolean context; private String defaultValue; /** * Constructs an instance. * * @param annotations array or parameter annotations */ public AnnotationsHelper(List annotations, Type _type) { String rsDefault = null; if (annotations != null) { for (Annotation item : annotations) { if ("javax.ws.rs.core.Context".equals(item.annotationType().getName())) { context = true; } else if ("javax.ws.rs.DefaultValue".equals(item.annotationType().getName())) { try { rsDefault = (String) item.annotationType().getMethod("value").invoke(item); } catch (Exception ex) { LOGGER.error("Invocation of value method failed", ex); } } } } defaultValue = rsDefault; } /** */ public boolean isContext() { return context; } /** * Returns default value from annotation. * * @return default value from annotation */ public String getDefaultValue() { return defaultValue; } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/PathUtils.java ================================================ package io.swagger.v3.core.util; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class PathUtils { private static Logger LOGGER = LoggerFactory.getLogger(PathUtils.class); private static final char COLON = ':'; private static final char OPEN = '{'; private static final char CLOSE = '}'; private static final char SLASH = '/'; private static final Pattern TRIM_PATTERN = Pattern.compile("^/*(.*?)/*$"); public static String parsePath(String uri, Map patterns) { if (uri == null) { return null; } else if (StringUtils.isBlank(uri)) { return String.valueOf(SLASH); } CharacterIterator ci = new StringCharacterIterator(uri); StringBuilder pathBuffer = new StringBuilder(); char c = ci.first(); if (c == CharacterIterator.DONE) { return String.valueOf(SLASH); } do { if (c == OPEN) { String regexBuffer = cutParameter(ci, patterns); if (regexBuffer == null) { LOGGER.warn("Operation path \"{}\" contains syntax error.", uri); return null; } pathBuffer.append(regexBuffer); } else { int length = pathBuffer.length(); if (!(c == SLASH && (length != 0 && pathBuffer.charAt(length - 1) == SLASH))) { pathBuffer.append(c); } } } while ((c = ci.next()) != CharacterIterator.DONE); return pathBuffer.toString(); } public static String collectPath(String... pathParts) { final StringBuilder sb = new StringBuilder(); for (String item : pathParts) { if (StringUtils.isBlank(item)) { continue; } final String path = trimPath(item); if (StringUtils.isNotBlank(path)) { sb.append(SLASH).append(path); } } return sb.length() > 0 ? sb.toString() : String.valueOf(SLASH); } private static String trimPath(String value) { final Matcher matcher = TRIM_PATTERN.matcher(value); return matcher.find() && StringUtils.isNotBlank(matcher.group(1)) ? matcher.group(1) : null; } private static String cutParameter(CharacterIterator ci, Map patterns) { StringBuilder regexBuffer = new StringBuilder(); int braceCount = 1; for (char regexChar = ci.next(); regexChar != CharacterIterator.DONE; regexChar = ci.next()) { if (regexChar == OPEN) { braceCount++; } else if (regexChar == CLOSE) { braceCount--; if (braceCount == 0) { break; } } regexBuffer.append(regexChar); } if (braceCount != 0) { return null; } String regex = StringUtils.trimToNull(regexBuffer.toString()); if (regex == null) { return null; } StringBuilder pathBuffer = new StringBuilder(); pathBuffer.append(OPEN); int index = regex.indexOf(COLON); if (index != -1) { final String name = StringUtils.trimToNull(regex.substring(0, index)); final String value = StringUtils.trimToNull(regex.substring(index + 1, regex.length())); if (name != null) { pathBuffer.append(name); if (value != null) { patterns.put(name, value); } } else { return null; } } else { pathBuffer.append(regex); } pathBuffer.append(CLOSE); return pathBuffer.toString(); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Paths31Deserializer.java ================================================ package io.swagger.v3.core.util; public class Paths31Deserializer extends PathsDeserializer { public Paths31Deserializer() { this.openapi31 = true; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/PathsDeserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import java.io.IOException; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; public class PathsDeserializer extends JsonDeserializer { protected boolean openapi31; @Override public Paths deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { final ObjectMapper mapper; if (openapi31) { mapper = Json31.mapper(); } else { mapper = Json.mapper(); } Paths result = new Paths(); JsonNode node = jp.getCodec().readTree(jp); ObjectNode objectNode = (ObjectNode)node; Map extensions = new LinkedHashMap<>(); for (Iterator it = objectNode.fieldNames(); it.hasNext(); ) { String childName = it.next(); JsonNode child = objectNode.get(childName); // if name start with `x-` consider it an extesion if (childName.startsWith("x-")) { extensions.put(childName, mapper.convertValue(child, Object.class)); } else { result.put(childName, mapper.convertValue(child, PathItem.class)); } } if (!extensions.isEmpty()) { result.setExtensions(extensions); } return result; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/PrettyPrintHelper.java ================================================ package io.swagger.v3.core.util; import org.slf4j.Logger; import java.io.PrintWriter; import java.io.StringWriter; import java.util.function.Consumer; class PrettyPrintHelper { private static final ThreadLocal> OVERRIDE = new ThreadLocal<>(); private PrettyPrintHelper() { // utility class } static void setOverride(Consumer consumer) { OVERRIDE.set(consumer); } static void clearOverride() { OVERRIDE.remove(); } static void emit(Logger logger, String message) { Consumer consumer = OVERRIDE.get(); if (consumer != null) { consumer.accept(message); } else { logger.debug(message); } } static void emitError(Logger logger, String message, Throwable throwable) { Consumer consumer = OVERRIDE.get(); if (consumer != null) { StringBuilder builder = new StringBuilder(message); if (throwable != null) { builder.append(System.lineSeparator()); StringWriter writer = new StringWriter(); throwable.printStackTrace(new PrintWriter(writer)); builder.append(writer); } consumer.accept(builder.toString()); } logger.error(message, throwable); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/PrimitiveType.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.type.TypeFactory; import io.swagger.v3.oas.models.media.BinarySchema; import io.swagger.v3.oas.models.media.BooleanSchema; import io.swagger.v3.oas.models.media.ByteArraySchema; import io.swagger.v3.oas.models.media.DateSchema; import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.FileSchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.JsonSchema; import io.swagger.v3.oas.models.media.NumberSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.media.UUIDSchema; import org.apache.commons.lang3.StringUtils; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; /** * The PrimitiveType enumeration defines a mapping of limited set * of classes into Swagger primitive types. */ public enum PrimitiveType { STRING(String.class, "string") { @Override public Schema createProperty() { return new StringSchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string"); } }, BOOLEAN(Boolean.class, "boolean") { @Override public Schema createProperty() { return new BooleanSchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("boolean"); } }, BYTE(Byte.class, "byte") { @Override public Schema createProperty() { if ( (System.getProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY) != null && System.getProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY).equals(Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_STRING_SCHEMA.toString())) || (System.getenv(Schema.BINARY_STRING_CONVERSION_PROPERTY) != null && System.getenv(Schema.BINARY_STRING_CONVERSION_PROPERTY).equals(Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_STRING_SCHEMA.toString()))) { return new StringSchema().format("byte"); } return new ByteArraySchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("byte"); } }, BINARY(Byte.class, "binary") { @Override public Schema createProperty() { if ( (System.getProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY) != null && System.getProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY).equals(Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_STRING_SCHEMA.toString())) || (System.getenv(Schema.BINARY_STRING_CONVERSION_PROPERTY) != null && System.getenv(Schema.BINARY_STRING_CONVERSION_PROPERTY).equals(Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_STRING_SCHEMA.toString()))) { return new StringSchema().format("binary"); } return new BinarySchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("binary"); } }, URI(java.net.URI.class, "uri") { @Override public Schema createProperty() { return new StringSchema().format("uri"); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("uri"); } }, URL(java.net.URL.class, "url") { @Override public Schema createProperty() { return new StringSchema().format("url"); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("url"); } }, EMAIL(String.class, "email") { @Override public Schema createProperty() { return new StringSchema().format("email"); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("email"); } }, UUID(java.util.UUID.class, "uuid") { @Override public UUIDSchema createProperty() { return new UUIDSchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("uuid"); } }, INT(Integer.class, "integer") { @Override public IntegerSchema createProperty() { return new IntegerSchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("integer").format("int32"); } }, LONG(Long.class, "long") { @Override public Schema createProperty() { return new IntegerSchema().format("int64"); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("integer").format("int64"); } }, FLOAT(Float.class, "float") { @Override public Schema createProperty() { return new NumberSchema().format("float"); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("number").format("float"); } }, DOUBLE(Double.class, "double") { @Override public Schema createProperty() { return new NumberSchema().format("double"); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("number").format("double"); } }, INTEGER(java.math.BigInteger.class) { @Override public Schema createProperty() { return new IntegerSchema().format(null); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("integer"); } }, DECIMAL(java.math.BigDecimal.class, "number") { @Override public Schema createProperty() { return new NumberSchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("number"); } }, NUMBER(Number.class, "number") { @Override public Schema createProperty() { return new NumberSchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("number"); } }, DATE(DateStub.class, "date") { @Override public DateSchema createProperty() { return new DateSchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("date"); } }, DATE_TIME(java.util.Date.class, "date-time") { @Override public DateTimeSchema createProperty() { return new DateTimeSchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("date-time"); } }, PARTIAL_TIME(java.time.LocalTime.class, "partial-time") { @Override public Schema createProperty() { return new StringSchema().format("partial-time"); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("partial-time"); } }, FILE(java.io.File.class, "file") { @Override public FileSchema createProperty() { return new FileSchema(); } @Override public Schema createProperty31() { return new JsonSchema().typesItem("string").format("binary"); } }, OBJECT(Object.class) { @Override public Schema createProperty() { return explicitObjectType == null || explicitObjectType ? new Schema().type("object"): new Schema(); } @Override public Schema createProperty31() { return explicitObjectType == null || explicitObjectType ? new JsonSchema().typesItem("object") : new JsonSchema(); } }; public static Boolean explicitObjectType; private static final Map, PrimitiveType> KEY_CLASSES; private static final Map, Collection> MULTI_KEY_CLASSES; private static final Map, PrimitiveType> BASE_CLASSES; /** * Adds support of a small number of "well-known" types, specifically for * Joda lib. */ private static final Map EXTERNAL_CLASSES; /** * Allows to exclude specific classes from KEY_CLASSES mappings to primitive * */ private static Set customExcludedClasses = ConcurrentHashMap.newKeySet(); /** * Allows to exclude specific classes from EXTERNAL_CLASSES mappings to primitive * */ private static Set customExcludedExternalClasses = ConcurrentHashMap.newKeySet(); /** * Adds support for custom mapping of classes to primitive types */ private static Map customClasses = new ConcurrentHashMap<>(); /** * class qualified names prefixes to be considered as "system" types */ private static Set systemPrefixes = ConcurrentHashMap.newKeySet(); /** * class qualified names NOT to be considered as "system" types */ private static Set nonSystemTypes = ConcurrentHashMap.newKeySet(); /** * package names NOT to be considered as "system" types */ private static Set nonSystemTypePackages = ConcurrentHashMap.newKeySet(); /** * Alternative names for primitive types that have to be supported for * backward compatibility. */ private static final Map NAMES; private final Class keyClass; private final String commonName; public static final Map datatypeMappings; static { systemPrefixes.add("java."); systemPrefixes.add("javax."); nonSystemTypes.add("java.time.LocalTime"); final Map dms = new HashMap<>(); dms.put("integer_int32", "integer"); dms.put("integer_", "integer"); dms.put("integer_int64", "long"); dms.put("number_", "number"); dms.put("number_float", "float"); dms.put("number_double", "double"); dms.put("string_", "string"); dms.put("string_byte", "byte"); dms.put("string_email", "email"); dms.put("string_binary", "binary"); dms.put("string_uri", "uri"); dms.put("string_url", "url"); dms.put("string_uuid", "uuid"); dms.put("string_date", "date"); dms.put("string_date-time", "date-time"); dms.put("string_partial-time", "partial-time"); dms.put("string_password", "password"); dms.put("boolean_", "boolean"); dms.put("object_", "object"); datatypeMappings = Collections.unmodifiableMap(dms); final Map, PrimitiveType> keyClasses = new HashMap<>(); addKeys(keyClasses, BOOLEAN, Boolean.class, Boolean.TYPE); addKeys(keyClasses, STRING, String.class, Character.class, Character.TYPE); addKeys(keyClasses, BYTE, Byte.class, Byte.TYPE); addKeys(keyClasses, URL, java.net.URL.class); addKeys(keyClasses, URI, java.net.URI.class); addKeys(keyClasses, UUID, java.util.UUID.class); addKeys(keyClasses, INT, Integer.class, Integer.TYPE, Short.class, Short.TYPE); addKeys(keyClasses, LONG, Long.class, Long.TYPE); addKeys(keyClasses, FLOAT, Float.class, Float.TYPE); addKeys(keyClasses, DOUBLE, Double.class, Double.TYPE); addKeys(keyClasses, INTEGER, java.math.BigInteger.class); addKeys(keyClasses, DECIMAL, java.math.BigDecimal.class); addKeys(keyClasses, NUMBER, Number.class); addKeys(keyClasses, DATE, DateStub.class); addKeys(keyClasses, DATE_TIME, java.util.Date.class); addKeys(keyClasses, FILE, java.io.File.class); addKeys(keyClasses, OBJECT, Object.class); KEY_CLASSES = Collections.unmodifiableMap(keyClasses); final Map, Collection> multiKeyClasses = new HashMap<>(); addMultiKeys(multiKeyClasses, BYTE, byte[].class); addMultiKeys(multiKeyClasses, BINARY, byte[].class); MULTI_KEY_CLASSES = Collections.unmodifiableMap(multiKeyClasses); final Map, PrimitiveType> baseClasses = new HashMap<>(); addKeys(baseClasses, DATE_TIME, java.util.Date.class, java.util.Calendar.class); BASE_CLASSES = Collections.unmodifiableMap(baseClasses); final Map externalClasses = new HashMap<>(); addKeys(externalClasses, DATE, "org.joda.time.LocalDate", "java.time.LocalDate"); addKeys(externalClasses, DATE_TIME, "java.time.LocalDateTime", "java.time.ZonedDateTime", "java.time.OffsetDateTime", "javax.xml.datatype.XMLGregorianCalendar", "org.joda.time.LocalDateTime", "org.joda.time.ReadableDateTime", "org.joda.time.DateTime", "java.time.Instant"); EXTERNAL_CLASSES = Collections.unmodifiableMap(externalClasses); final Map names = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); for (PrimitiveType item : values()) { final String name = item.getCommonName(); if (name != null) { addKeys(names, item, name); } } addKeys(names, INT, "int"); addKeys(names, OBJECT, "object"); NAMES = Collections.unmodifiableMap(names); if (System.getenv(Schema.EXPLICIT_OBJECT_SCHEMA_PROPERTY) != null) { explicitObjectType = Boolean.parseBoolean(System.getenv(Schema.EXPLICIT_OBJECT_SCHEMA_PROPERTY)); } else if (System.getProperty(Schema.EXPLICIT_OBJECT_SCHEMA_PROPERTY) != null) { explicitObjectType = Boolean.parseBoolean(System.getProperty(Schema.EXPLICIT_OBJECT_SCHEMA_PROPERTY)); } } private PrimitiveType(Class keyClass) { this(keyClass, null); } private PrimitiveType(Class keyClass, String commonName) { this.keyClass = keyClass; this.commonName = commonName; } /** * Adds support for custom mapping of classes to primitive types * * @return Map of custom classes to primitive type * @since 2.0.6 */ public static Set customExcludedClasses() { return customExcludedClasses; } /** * Adds support for custom mapping of classes to primitive types * * @return Map of custom classes to primitive type * @since 2.1.2 */ public static Set customExcludedExternalClasses() { return customExcludedExternalClasses; } /** * Adds support for custom mapping of classes to primitive types * * @return Map of custom classes to primitive type * @since 2.0.6 */ public static Map customClasses() { return customClasses; } /** * class qualified names prefixes to be considered as "system" types * * @return Mutable set of class qualified names prefixes to be considered as "system" types * @since 2.0.6 */ public static Set systemPrefixes() { return systemPrefixes; } /** * class qualified names NOT to be considered as "system" types * * @return Mutable set of class qualified names NOT to be considered as "system" types * @since 2.0.6 */ public static Set nonSystemTypes() { return nonSystemTypes; } /** * package names NOT to be considered as "system" types * * @return Mutable set of package names NOT to be considered as "system" types * @since 2.0.6 */ public static Set nonSystemTypePackages() { return nonSystemTypePackages; } public static PrimitiveType fromTypeAndFormat(Type type, String format) { final Class raw = TypeFactory.defaultInstance().constructType(type).getRawClass(); final Collection keys = MULTI_KEY_CLASSES.get(raw); if (keys == null || keys.isEmpty() || StringUtils.isBlank(format)) { return fromType(type); } else { return keys .stream() .filter(t -> t.getCommonName().equalsIgnoreCase(format)) .findAny() .orElse(null); } } public static PrimitiveType fromType(Type type) { final Class raw = TypeFactory.defaultInstance().constructType(type).getRawClass(); final PrimitiveType key = KEY_CLASSES.get(raw); if (key != null) { if (!customExcludedClasses.contains(raw.getName())) { return key; } } final Collection keys = MULTI_KEY_CLASSES.get(raw); if (keys != null && !keys.isEmpty()) { final PrimitiveType first = keys.iterator().next(); if (!customExcludedClasses.contains(raw.getName())) { return first; } } final PrimitiveType custom = customClasses.get(raw.getName()); if (custom != null) { return custom; } final PrimitiveType external = EXTERNAL_CLASSES.get(raw.getName()); if (external != null) { if (!customExcludedExternalClasses().contains(raw.getName())) { return external; } } for (Map.Entry, PrimitiveType> entry : BASE_CLASSES.entrySet()) { if (entry.getKey().isAssignableFrom(raw)) { return entry.getValue(); } } return null; } public static PrimitiveType fromName(String name) { if (name == null) { return null; } PrimitiveType fromName = NAMES.get(name); if (fromName == null) { if (!customExcludedExternalClasses().contains(name)) { fromName = EXTERNAL_CLASSES.get(name); } } return fromName; } public static PrimitiveType fromTypeAndFormat(String type, String format) { if (StringUtils.isNotBlank(type) && type.equals("object")) { return null; } return fromName(datatypeMappings.get(String.format("%s_%s", StringUtils.isBlank(type) ? "" : type, StringUtils.isBlank(format) ? "" : format))); } public static Schema createProperty(Type type) { return createProperty(type, false); } public static Schema createProperty(Type type, boolean openapi31) { final PrimitiveType item = fromType(type); return item == null ? null : openapi31 ? item.createProperty31() : item.createProperty(); } public static Schema createProperty(String name) { return createProperty(name, false); } public static Schema createProperty(String name, boolean openapi31) { final PrimitiveType item = fromName(name); return item == null ? null : openapi31 ? item.createProperty31() : item.createProperty(); } public static String getCommonName(Type type) { final PrimitiveType item = fromType(type); return item == null ? null : item.getCommonName(); } public Class getKeyClass() { return keyClass; } public String getCommonName() { return commonName; } public abstract Schema createProperty(); public abstract Schema createProperty31(); private static void addKeys(Map map, PrimitiveType type, K... keys) { for (K key : keys) { map.put(key, type); } } private static void addMultiKeys(Map> map, PrimitiveType type, K... keys) { for (K key : keys) { if (!map.containsKey(key)) { map.put(key, new ArrayList<>()); } map.get(key).add(type); } } private static class DateStub { private DateStub() { } } /** * Convenience method to map LocalTime to string primitive with rfc3339 format partial-time. * See https://xml2rfc.tools.ietf.org/public/rfc/html/rfc3339.html#anchor14 * * @since 2.0.6 */ public static void enablePartialTime() { customClasses().put("org.joda.time.LocalTime", PrimitiveType.PARTIAL_TIME); customClasses().put("java.time.LocalTime", PrimitiveType.PARTIAL_TIME); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/RefUtils.java ================================================ package io.swagger.v3.core.util; import io.swagger.v3.oas.models.Components; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; public class RefUtils { public static String constructRef(String simpleRef) { return Components.COMPONENTS_SCHEMAS_REF + simpleRef; } public static String constructRef(String simpleRef, String prefix) { return prefix + simpleRef; } public static Pair extractSimpleName(String ref) { int idx = ref.lastIndexOf('/'); if (idx > 0) { String simple = ref.substring(idx + 1); if (!StringUtils.isBlank(simple)) { return new ImmutablePair<>(simple, ref.substring(0, idx + 1)); } } return new ImmutablePair<>(ref, null); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ReferenceTypeUtils.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.JavaType; import io.swagger.v3.core.converter.AnnotatedType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Arrays; public abstract class ReferenceTypeUtils { private static Logger LOGGER = LoggerFactory.getLogger(ReferenceTypeUtils.class); public static boolean _isReferenceType(JavaType jtype) { return Arrays.asList("com.google.common.base.Optional", "java.util.Optional") .contains(jtype.getRawClass().getCanonicalName()) || jtype.isReferenceType(); } /** * check if type is a reference type, returns the unwrapped type in case, otherwise null * * @param type */ public static AnnotatedType unwrapReference(AnnotatedType type) { if (type == null) { return type; } else if (type.getType() == null) { return null; } try { final JavaType jtype; if (type.getType() instanceof JavaType) { jtype = (JavaType) type.getType(); } else { jtype = Json.mapper().constructType(type.getType()); } if (_isReferenceType(jtype)) { AnnotatedType aType = new AnnotatedType() .type(jtype.containedType(0)) .name(type.getName()) .parent(type.getParent()) .jsonUnwrappedHandler(type.getJsonUnwrappedHandler()) .skipOverride(type.isSkipOverride()) .schemaProperty(type.isSchemaProperty()) .ctxAnnotations(type.getCtxAnnotations()) .resolveAsRef(type.isResolveAsRef()) .jsonViewAnnotation(type.getJsonViewAnnotation()) .skipSchemaName(type.isSkipSchemaName()) .skipJsonIdentity(type.isSkipJsonIdentity()) .components(type.getComponents()) .propertyName(type.getPropertyName()); return aType; } else { return null; } } catch (Exception e) { LOGGER.error("Error unwrapping optional", e); return null; } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ReflectionUtils.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; public class ReflectionUtils { private static final Logger LOGGER = LoggerFactory.getLogger(ReflectionUtils.class); public static Type typeFromString(String type) { final PrimitiveType primitive = PrimitiveType.fromName(type); if (primitive != null) { return primitive.getKeyClass(); } try { return loadClassByName(type); } catch (Exception e) { LOGGER.warn(String.format("Failed to resolve '%s' into class", type), e); } return null; } /** * Load Class by class name. If class not found in it's Class loader or one of the parent class loaders - delegate to the Thread's ContextClassLoader * * @param className Canonical class name * @return Class definition of className * @throws ClassNotFoundException */ public static Class loadClassByName(String className) throws ClassNotFoundException { try { return Class.forName(className); } catch (ClassNotFoundException e) { return Thread.currentThread().getContextClassLoader().loadClass(className); } } /** * Checks if the method methodToFind is the overridden method from the superclass or superinterface. * * @param methodToFind is method to check * @param cls is method class * @return true if the method is overridden method */ public static boolean isOverriddenMethod(Method methodToFind, Class cls) { if (!hasOverriddenMethods(methodToFind, cls)) { return false; } Set> superClasses = new HashSet<>(); Collections.addAll(superClasses, cls.getInterfaces()); if (cls.getSuperclass() != null) { superClasses.add(cls.getSuperclass()); } for (Class superClass : superClasses) { if (superClass != null && !(superClass.equals(Object.class))) { try { Method found = superClass.getMethod(methodToFind.getName(), methodToFind.getParameterTypes()); if (found.getReturnType().equals(methodToFind.getReturnType())) { if (!methodToFind.getDeclaringClass().equals(superClass)){ return true; } else { if (getOverriddenMethod(found) == null) { return true; } } } } catch (NoSuchMethodException e) { // expected } if (isOverriddenMethod(methodToFind, superClass)) { return true; } } } return false; } public static boolean hasOverriddenMethods(Method methodToFind, Class cls) { if (cls == null || methodToFind == null) { return false; } boolean found = false; for (Method method: cls.getMethods()) { boolean equalsMethodName = method.getName().equals(methodToFind.getName()); boolean superClassReturnAssignable = method.getReturnType().isAssignableFrom(methodToFind.getReturnType()); boolean classReturnAssignable = methodToFind.getReturnType().isAssignableFrom(method.getReturnType()); boolean equalsParamCount = method.getParameterCount() == methodToFind.getParameterCount(); if (equalsMethodName && equalsParamCount && (superClassReturnAssignable || classReturnAssignable)){ Class[] paramsToFind = methodToFind.getParameterTypes(); if (paramsToFind == null || paramsToFind.length == 0) { continue; } boolean assignableParams = true; for (int i = 0; i < paramsToFind.length; i++) { boolean superClassParamAssignable = method.getParameterTypes()[i].isAssignableFrom(paramsToFind[i]); boolean classParamAssignable = paramsToFind[i].isAssignableFrom(method.getParameterTypes()[i]); if (!superClassParamAssignable && !classParamAssignable) { assignableParams = false; } } if (assignableParams) { if (!found) { found = true; } else { return true; } } } } return false; } /** * Returns overridden method from superclass if it exists. If method was not found returns null. * * @param method is method to find * @return overridden method from superclass */ public static Method getOverriddenMethod(Method method) { Class declaringClass = method.getDeclaringClass(); Class superClass = declaringClass.getSuperclass(); Method result = null; if (superClass != null && !(superClass.equals(Object.class))) { result = findMethod(method, superClass); } if (result == null) { for (Class anInterface : declaringClass.getInterfaces()) { result = findMethod(method, anInterface); if (result != null) { return result; } } } return result; } /** * Searches the field name in given class cls. If the field is found returns it, else return null. * * @param name is the field to search * @param cls is the class or interface where to search * @return field if it is found */ public static Field findField(String name, Class cls) { if (cls == null) { return null; } try { return cls.getField(name); } catch (NoSuchFieldException nsfe) { return null; } } /** * Searches the method methodToFind in given class cls. If the method is found returns it, else return null. * * @param methodToFind is the method to search * @param cls is the class or interface where to search * @return method if it is found */ public static Method findMethod(Method methodToFind, Class cls) { if (cls == null) { return null; } String methodToSearch = methodToFind.getName(); Class[] soughtForParameterType = methodToFind.getParameterTypes(); Type[] soughtForGenericParameterType = methodToFind.getGenericParameterTypes(); for (Method method : cls.getMethods()) { if (method.getName().equals(methodToSearch) && method.getReturnType().isAssignableFrom(methodToFind.getReturnType())) { Class[] srcParameterTypes = method.getParameterTypes(); Type[] srcGenericParameterTypes = method.getGenericParameterTypes(); if (soughtForParameterType.length == srcParameterTypes.length && soughtForGenericParameterType.length == srcGenericParameterTypes.length) { if (hasIdenticalParameters(srcParameterTypes, soughtForParameterType, srcGenericParameterTypes, soughtForGenericParameterType)) { return method; } } } } return null; } private static boolean hasIdenticalParameters(Class[] srcParameterTypes, Class[] soughtForParameterType, Type[] srcGenericParameterTypes, Type[] soughtForGenericParameterType) { for (int j = 0; j < soughtForParameterType.length; j++) { Class parameterType = soughtForParameterType[j]; if (!(srcParameterTypes[j].equals(parameterType) || (!srcGenericParameterTypes[j].equals(soughtForGenericParameterType[j]) && srcParameterTypes[j].isAssignableFrom(parameterType)))) { return false; } } return true; } public static boolean isInject(List annotations) { for (Annotation annotation : annotations) { // use string name to avoid additional dependencies if ("javax.inject.Inject".equals(annotation.annotationType().getName())) { return true; } } return false; } public static boolean isConstructorCompatible(Constructor constructor) { if (!Modifier.isPublic(constructor.getModifiers())) { final int access = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE; return constructor.getParameterTypes().length == 0 && (constructor.getDeclaringClass().getModifiers() & access) == constructor.getModifiers(); } return true; } /** * Returns the list of declared fields from the class cls and its superclasses * excluding Object class. If the field from child class hides the field from superclass, * the field from superclass won't be added to the result list. * * The list is sorted by name to make the output of this method deterministic. * See https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getFields-- * * @param cls is the processing class * @return list of Fields */ public static List getDeclaredFields(Class cls) { if (cls == null || Object.class.equals(cls)) { return Collections.emptyList(); } final List fields = new ArrayList<>(); final Set fieldNames = new HashSet<>(); for (Field field : cls.getDeclaredFields()) { fields.add(field); fieldNames.add(field.getName()); } for (Field field : getDeclaredFields(cls.getSuperclass())) { if (!fieldNames.contains(field.getName())) { fields.add(field); } } // Make sure the order is deterministic fields.sort(Comparator.comparing(Field::getName)); return fields; } /** * Returns an annotation by type from a method. * * @param method is the method to find * @param annotationClass is the type of annotation * @param is the type of annotation * @return annotation if it is found */ public static A getAnnotation(Method method, Class annotationClass) { A annotation = method.getAnnotation(annotationClass); if (annotation == null) { for (Annotation metaAnnotation : method.getAnnotations()) { annotation = metaAnnotation.annotationType().getAnnotation(annotationClass); if (annotation != null) { return annotation; } } Method superclassMethod = getOverriddenMethod(method); if (superclassMethod != null) { annotation = getAnnotation(superclassMethod, annotationClass); } } return annotation; } public static A getAnnotation(Class cls, Class annotationClass) { A annotation = cls.getAnnotation(annotationClass); if (annotation == null) { for (Annotation metaAnnotation : cls.getAnnotations()) { annotation = metaAnnotation.annotationType().getAnnotation(annotationClass); if (annotation != null) { return annotation; } } Class superClass = cls.getSuperclass(); if (superClass != null && !(superClass.equals(Object.class))) { annotation = getAnnotation(superClass, annotationClass); } } if (annotation == null) { for (Class anInterface : cls.getInterfaces()) { for (Annotation metaAnnotation : anInterface.getAnnotations()) { annotation = metaAnnotation.annotationType().getAnnotation(annotationClass); if (annotation != null) { return annotation; } } annotation = getAnnotation(anInterface, annotationClass); if (annotation != null) { return annotation; } } } return annotation; } /** * Returns a List of repeatable annotations by type from a method. * * @param method is the method to find * @param annotationClass is the type of annotation * @param is the type of annotation * @return List of repeatable annotations if it is found */ public static List getRepeatableAnnotations(Method method, Class annotationClass) { Set annotationsSet = new LinkedHashSet<>(); A[] annotations = method.getAnnotationsByType(annotationClass); if (annotations != null) { annotationsSet.addAll(Arrays.asList(annotations)); } for (Annotation metaAnnotation : method.getAnnotations()) { annotations = metaAnnotation.annotationType().getAnnotationsByType(annotationClass); if (annotations != null && annotations.length > 0) { annotationsSet.addAll(Arrays.asList(annotations)); } } Method superclassMethod = getOverriddenMethod(method); if (superclassMethod != null) { List superAnnotations = getRepeatableAnnotations(superclassMethod, annotationClass); if (superAnnotations != null) { annotationsSet.addAll(superAnnotations); } } if (annotationsSet.isEmpty()) { return null; } return new ArrayList<>(annotationsSet); } public static List getRepeatableAnnotations(Class cls, Class annotationClass) { A[] annotations = getRepeatableAnnotationsArray(cls, annotationClass); if (annotations == null || annotations.length == 0) { return null; } return Arrays.asList(annotations); } public static A[] getRepeatableAnnotationsArray(Class cls, Class annotationClass) { A[] annotations = cls.getAnnotationsByType(annotationClass); if (annotations == null || annotations.length == 0) { for (Annotation metaAnnotation : cls.getAnnotations()) { annotations = metaAnnotation.annotationType().getAnnotationsByType(annotationClass); if (annotations != null && annotations.length > 0) { return annotations; } } Class superClass = cls.getSuperclass(); if (superClass != null && !(superClass.equals(Object.class))) { annotations = getRepeatableAnnotationsArray(superClass, annotationClass); } } if (annotations == null || annotations.length == 0) { for (Class anInterface : cls.getInterfaces()) { for (Annotation metaAnnotation : anInterface.getAnnotations()) { annotations = metaAnnotation.annotationType().getAnnotationsByType(annotationClass); if (annotations != null && annotations.length > 0) { return annotations; } } annotations = getRepeatableAnnotationsArray(anInterface, annotationClass); if (annotations != null) { return annotations; } } } return annotations; } public static Annotation[][] getParameterAnnotations(Method method) { Annotation[][] methodAnnotations = method.getParameterAnnotations(); Method overriddenmethod = getOverriddenMethod(method); while (overriddenmethod != null) { Annotation[][] overriddenAnnotations = overriddenmethod .getParameterAnnotations(); for (int i = 0; i < methodAnnotations.length; i++) { List types = new ArrayList<>(); for (int j = 0; j < methodAnnotations[i].length; j++) { types.add(methodAnnotations[i][j].annotationType()); } for (int j = 0; j < overriddenAnnotations[i].length; j++) { if (!types.contains(overriddenAnnotations[i][j] .annotationType())) { methodAnnotations[i] = ArrayUtils.add( methodAnnotations[i], overriddenAnnotations[i][j]); } } } overriddenmethod = getOverriddenMethod(overriddenmethod); } return methodAnnotations; } /** * Checks if the type is void. * * @param type is the type to check * @return true if the type is void */ public static boolean isVoid(Type type) { final Class cls = TypeFactory.defaultInstance().constructType(type).getRawClass(); return Void.class.isAssignableFrom(cls) || Void.TYPE.isAssignableFrom(cls); } public static boolean isSystemType(JavaType type) { return isSystemTypeNotArray(type) ? true : type.isArrayType(); } public static boolean isSystemTypeNotArray(JavaType type) { // used while resolving container types to skip resolving system types; possibly extend by checking classloader // and/or other packages for (String systemPrefix: PrimitiveType.systemPrefixes()) { if (type.getRawClass().getName().startsWith(systemPrefix)) { if ( !PrimitiveType.nonSystemTypes().contains(type.getRawClass().getName()) && !PrimitiveType.nonSystemTypePackages().contains(type.getRawClass().getPackage().getName())) { return true; } } } return false; } /** * A utility method to get an optional containing result from method or empty optional if unable to access * * @param method from reflect, a method of a class or interface * @param obj the class object in which the method exists * @param args varags of the parameters passed to the method * @return the result of the method, or empty conditional */ public static Optional safeInvoke(Method method, Object obj, Object... args) { try { return Optional.ofNullable(method.invoke(obj, args)); } catch (IllegalAccessException | InvocationTargetException e) { return Optional.empty(); } } /** * A utility method to get an optional containing value of field or empty optional if unable to access * * @param field from reflect, a field of a class or interface * @param obj the class object in which the field exists * @return optional containing the value of the field on the specified object, or empty optional */ public static Optional safeGet(Field field, Object obj) { try { return Optional.ofNullable(field.get(obj)); } catch (IllegalAccessException e) { return Optional.empty(); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/SchemaTypeUtils.java ================================================ package io.swagger.v3.core.util; import io.swagger.v3.oas.models.media.Schema; public class SchemaTypeUtils { private static final String OBJECT_TYPE = "object"; private static final String ARRAY_TYPE = "array"; private static final String STRING_TYPE = "string"; private static final String NUMBER_TYPE = "number"; private static final String INTEGER_TYPE = "integer"; public static boolean isObjectSchema(Schema schema) { return isSchemaType(schema, OBJECT_TYPE) || (schema.getType() == null && (hasProperties(schema) || hasPatternProperties(schema))); } public static boolean isArraySchema(Schema schema) { return isSchemaType(schema, ARRAY_TYPE); } public static boolean isStringSchema(Schema schema) { return isSchemaType(schema, STRING_TYPE); } public static boolean isNumberSchema(Schema schema) { return isSchemaType(schema, NUMBER_TYPE) || isSchemaType(schema, INTEGER_TYPE); } private static boolean isSchemaType(Schema schema, String type) { return type.equals(schema.getType()) || isSchemaType31(schema, type); } private static boolean isSchemaType31(Schema schema, String type) { return schema.getTypes() != null && schema.getTypes().contains(type); } private static boolean hasProperties(Schema schema) { return schema.getProperties() != null && !schema.getProperties().isEmpty(); } private static boolean hasPatternProperties(Schema schema) { return schema.getPatternProperties() != null && !schema.getPatternProperties().isEmpty(); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/SecurityScheme31Deserializer.java ================================================ package io.swagger.v3.core.util; public class SecurityScheme31Deserializer extends SecuritySchemeDeserializer { public SecurityScheme31Deserializer() { openapi31 = true; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/SecuritySchemeDeserializer.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.models.security.OAuthFlows; import io.swagger.v3.oas.models.security.SecurityScheme; import java.io.IOException; import java.util.Arrays; import java.util.Iterator; import java.util.List; public class SecuritySchemeDeserializer extends JsonDeserializer { protected boolean openapi31; @Override public SecurityScheme deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { ObjectMapper mapper = null; if (openapi31) { mapper = Json31.mapper(); } else { mapper = Json.mapper(); } SecurityScheme result = null; JsonNode node = jp.getCodec().readTree(jp); JsonNode inNode = node.get("type"); if (inNode != null) { String type = inNode.asText(); if (Arrays.stream(SecurityScheme.Type.values()).noneMatch(t -> t.toString().equals(type))) { // wrong type, throw exception throw new JsonParseException(jp, String.format("SecurityScheme type %s not allowed", type)); } result = new SecurityScheme() .description(getFieldText("description", node)); if ("http".equals(type)) { result .type(SecurityScheme.Type.HTTP) .scheme(getFieldText("scheme", node)) .bearerFormat(getFieldText("bearerFormat", node)); } else if ("apiKey".equals(type)) { result .type(SecurityScheme.Type.APIKEY) .name(getFieldText("name", node)) .in(getIn(getFieldText("in", node))); } else if ("openIdConnect".equals(type)) { result .type(SecurityScheme.Type.OPENIDCONNECT) .openIdConnectUrl(getFieldText("openIdConnectUrl", node)); } else if ("oauth2".equals(type)) { result .type(SecurityScheme.Type.OAUTH2) .flows(mapper.convertValue(node.get("flows"), OAuthFlows.class)); } else if ("mutualTLS".equals(type)) { result .type(SecurityScheme.Type.MUTUALTLS); } final Iterator fieldNames = node.fieldNames(); while(fieldNames.hasNext()) { final String fieldName = fieldNames.next(); if(fieldName.startsWith("x-")) { final JsonNode fieldValue = node.get(fieldName); final Object value = Json.mapper().treeToValue(fieldValue, Object.class); result.addExtension(fieldName, value); } } } return result; } private SecurityScheme.In getIn(String value) { return Arrays.stream(SecurityScheme.In.values()).filter(i -> i.toString().equals(value)).findFirst().orElse(null); } private String getFieldText(String fieldName, JsonNode node) { JsonNode inNode = node.get(fieldName); if (inNode != null) { return inNode.asText(); } return null; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/SiblingAnnotationFilter.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.JavaType; import io.swagger.v3.oas.models.media.Schema; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; public class SiblingAnnotationFilter { public static class FilterResult { private final Annotation[] filteredAnnotations; private final Schema.SchemaResolution resolvedSchemaResolution; public FilterResult(Annotation[] filteredAnnotations, Schema.SchemaResolution resolvedSchemaResolution) { this.filteredAnnotations = filteredAnnotations; this.resolvedSchemaResolution = resolvedSchemaResolution; } public Annotation[] getFilteredAnnotations() { return filteredAnnotations; } public Schema.SchemaResolution getResolvedSchemaResolution() { return resolvedSchemaResolution; } } /** * Filter out Schema/ArraySchema annotations to prevent duplicate processing: * 1. They are already processed and merged by AnnotationsUtils.mergeSchemaAnnotations() * 2. Re-processing would cause annotation metadata to leak incorrectly between levels * 3. Without preserving ArraySchema, Stream is treated as generic object instead of iterable collection. * * The ArraySchema is needed for the Stream to be recognized as an array, but it doesn't leak to items * * because the container path filters it out. * * @param annotations the annotations to filter * @param propType the property type * @param ctxSchema the schema annotation * @param ctxArraySchema the array schema annotation * @param schemaResolution the schema resolution configuration * @param openapi31 whether OpenAPI 3.1 is enabled * @return FilterResult containing the filtered annotations and resolved schema resolution */ public static FilterResult filterSiblingAnnotations( Annotation[] annotations, JavaType propType, io.swagger.v3.oas.annotations.media.Schema ctxSchema, io.swagger.v3.oas.annotations.media.ArraySchema ctxArraySchema, Schema.SchemaResolution schemaResolution, boolean openapi31) { Annotation[] ctxFilteredSiblingAnnotations = null; Schema.SchemaResolution resolvedSchemaResolution = AnnotationsUtils.resolveSchemaResolution(schemaResolution, ctxSchema); if (AnnotationsUtils.areSiblingsAllowed(resolvedSchemaResolution, openapi31)) { List filteredAnnotationsList = new ArrayList<>(); if (annotations != null) { boolean isStreamWithArraySchema = isStreamType(propType) && ctxArraySchema != null; for (Annotation a : annotations) { boolean isSchemaAnnotation = a instanceof io.swagger.v3.oas.annotations.media.Schema; boolean isArraySchemaAnnotation = a instanceof io.swagger.v3.oas.annotations.media.ArraySchema; boolean shouldIncludeAnnotation = (!isSchemaAnnotation && !isArraySchemaAnnotation) || isStreamWithArraySchema; if (shouldIncludeAnnotation) { filteredAnnotationsList.add(a); } } ctxFilteredSiblingAnnotations = filteredAnnotationsList.toArray(new Annotation[filteredAnnotationsList.size()]); } } return new FilterResult(ctxFilteredSiblingAnnotations, resolvedSchemaResolution); } private static boolean isStreamType(JavaType type) { return type != null && type.getRawClass() != null && java.util.stream.Stream.class.isAssignableFrom(type.getRawClass()); } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ValidationAnnotationsUtils.java ================================================ package io.swagger.v3.core.util; import io.swagger.v3.oas.models.media.Schema; import javax.validation.constraints.*; import java.math.BigDecimal; import static io.swagger.v3.core.util.SchemaTypeUtils.*; public class ValidationAnnotationsUtils { public static final String JAVAX_NOT_NULL = "javax.validation.constraints.NotNull"; public static final String JAVAX_NOT_EMPTY = "javax.validation.constraints.NotEmpty"; public static final String JAVAX_NOT_BLANK = "javax.validation.constraints.NotBlank"; public static final String JAVAX_MIN = "javax.validation.constraints.Min"; public static final String JAVAX_MAX = "javax.validation.constraints.Max"; public static final String JAVAX_SIZE = "javax.validation.constraints.Size"; public static final String JAVAX_DECIMAL_MIN = "javax.validation.constraints.DecimalMin"; public static final String JAVAX_DECIMAL_MAX = "javax.validation.constraints.DecimalMax"; public static final String JAVAX_PATTERN = "javax.validation.constraints.Pattern"; public static final String JAVAX_EMAIL = "javax.validation.constraints.Email"; private static final String SCHEMA_EMAIL_FORMAT_NAME = "email"; /** * @param schema the schema * @param ctxSchema the schema's {@link io.swagger.v3.oas.annotations.media.Schema} annotation * @param ctxArraySchema the schema's {@link io.swagger.v3.oas.annotations.media.ArraySchema} annotation * @return whether the schema has been modified or not */ public static boolean applyNotEmptyConstraint(Schema schema, io.swagger.v3.oas.annotations.media.Schema ctxSchema, io.swagger.v3.oas.annotations.media.ArraySchema ctxArraySchema) { if (isArraySchema(schema)) { if (ctxArraySchema == null || ctxArraySchema.minItems() == Integer.MAX_VALUE) { schema.setMinItems(1); return true; } } else if (isStringSchema(schema)) { if (ctxSchema == null || ctxSchema.minLength() == 0) { schema.setMinLength(1); return true; } } else if (isObjectSchema(schema)) { if (ctxSchema == null || ctxSchema.minProperties() == 0) { schema.setMinProperties(1); return true; } } return false; } /** * @param schema the schema * @param ctxSchema the schema's {@link io.swagger.v3.oas.annotations.media.Schema} annotation * @return whether the schema has been modified or not */ public static boolean applyNotBlankConstraint(Schema schema, io.swagger.v3.oas.annotations.media.Schema ctxSchema) { if (isStringSchema(schema)) { if (ctxSchema == null || ctxSchema.minLength() == 0) { schema.setMinLength(1); return true; } } return false; } /** * @param schema the schema * @param annotation the schema's {@link Min} annotation * @return whether the schema has been modified or not */ public static boolean applyMinConstraint(Schema schema, Min annotation) { if (isNumberSchema(schema)) { schema.setMinimum(new BigDecimal(annotation.value())); return true; } return false; } /** * @param schema the schema * @param annotation the schema's {@link Max} annotation * @return whether the schema has been modified or not */ public static boolean applyMaxConstraint(Schema schema, Max annotation) { if (isNumberSchema(schema)) { schema.setMaximum(new BigDecimal(annotation.value())); return true; } return false; } /** * @param schema the schema * @param annotation the schema's {@link Size} annotation * @return whether the schema has been modified or not */ public static boolean applySizeConstraint(Schema schema, Size annotation) { if (isNumberSchema(schema)) { schema.setMinimum(new BigDecimal(annotation.min())); schema.setMaximum(new BigDecimal(annotation.max())); return true; } if (isStringSchema(schema)) { schema.setMinLength(annotation.min()); schema.setMaxLength(annotation.max()); return true; } if (isArraySchema(schema)) { schema.setMinItems(annotation.min()); schema.setMaxItems(annotation.max()); return true; } return false; } /** * @param schema the schema * @param annotation the schema's {@link DecimalMin} annotation * @return whether the schema has been modified or not */ public static boolean applyDecimalMinConstraint(Schema schema, DecimalMin annotation) { if (isNumberSchema(schema)) { schema.setMinimum(new BigDecimal(annotation.value())); schema.setExclusiveMinimum(!annotation.inclusive()); return true; } return false; } /** * @param schema the schema * @param annotation the schema's {@link DecimalMax} annotation * @return whether the schema has been modified or not */ public static boolean applyDecimalMaxConstraint(Schema schema, DecimalMax annotation) { if (isNumberSchema(schema)) { schema.setMaximum(new BigDecimal(annotation.value())); schema.setExclusiveMaximum(!annotation.inclusive()); return true; } return false; } /** * @param schema the schema * @param annotation the schema's {@link Pattern} annotation * @return whether the schema has been modified or not */ public static boolean applyPatternConstraint(Schema schema, Pattern annotation) { if (isStringSchema(schema)) { schema.setPattern(annotation.regexp()); return true; } if (schema.getItems() != null && isStringSchema(schema.getItems())) { schema.getItems().setPattern(annotation.regexp()); return true; } return false; } /** * @param schema the schema * @param annotation the schema's {@link Email} annotation * @return whether the schema has been modified or not */ public static boolean applyEmailConstraint(Schema schema, Email annotation) { if (isStringSchema(schema)) { schema.setFormat(SCHEMA_EMAIL_FORMAT_NAME); return true; } if (schema.getItems() != null && isStringSchema(schema.getItems())) { schema.getItems().setFormat(SCHEMA_EMAIL_FORMAT_NAME); return true; } return false; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/ValidatorProcessor.java ================================================ package io.swagger.v3.core.util; import io.swagger.v3.oas.models.media.Schema; import java.lang.annotation.Annotation; import java.util.Map; import java.util.Set; public interface ValidatorProcessor { enum MODE { BEFORE, REPLACE, AFTER } public default MODE getMode() { return MODE.REPLACE; } public default boolean applyBeanValidatorAnnotations(Schema property, Annotation[] annotations, Schema parent, boolean applyNotNullAnnotations) { return false; } public default Set resolveInvocationGroups(Map annos) { return null; } public default Set resolveInvocationAnnotations(Annotation[] annotations) { return null; } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Yaml { private static final class ObjectMapperHolder { private static final ObjectMapper MAPPER = ObjectMapperFactory.createYaml(); } private static final Logger LOGGER = LoggerFactory.getLogger(Yaml.class); public static ObjectMapper mapper() { return ObjectMapperHolder.MAPPER; } public static ObjectWriter pretty() { return mapper().writer(new DefaultPrettyPrinter()); } public static String pretty(Object o) { try { return pretty().writeValueAsString(o); } catch (Exception e) { PrettyPrintHelper.emitError(LOGGER, "Error serializing object to YAML", e); return null; } } public static void prettyPrint(Object o) { try { String prettyString = pretty().writeValueAsString(o); PrettyPrintHelper.emit(LOGGER, prettyString); } catch (Exception e) { PrettyPrintHelper.emitError(LOGGER, "Error pretty-printing YAML", e); } } } ================================================ FILE: modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml31.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import io.swagger.v3.oas.models.media.Schema; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; public class Yaml31 { private static final class ObjectMapperHolder { private static final ObjectMapper MAPPER = ObjectMapperFactory.createYaml31(); } private static final Logger LOGGER = LoggerFactory.getLogger(Yaml31.class); public static ObjectMapper mapper() { return ObjectMapperHolder.MAPPER; } public static ObjectWriter pretty() { return mapper().writer(new DefaultPrettyPrinter()); } public static String pretty(Object o) { try { return pretty().writeValueAsString(o); } catch (Exception e) { PrettyPrintHelper.emitError(LOGGER, "Error serializing object to YAML (3.1)", e); return null; } } public static void prettyPrint(Object o) { try { String prettyString = pretty().writeValueAsString(o); PrettyPrintHelper.emit(LOGGER, prettyString); } catch (Exception e) { PrettyPrintHelper.emitError(LOGGER, "Error pretty-printing YAML (3.1)", e); } } public static Map jsonSchemaAsMap(String jsonSchema) { try { return mapper().readValue(jsonSchema, Map.class); } catch (JsonProcessingException e) { LOGGER.error("Exception converting jsonSchema to Map", e); return null; } } public static Map jsonSchemaAsMap(Schema schema) { try { return mapper().readValue(mapper().writeValueAsString(schema), Map.class); } catch (JsonProcessingException e) { LOGGER.error("Exception converting jsonSchema to Map", e); return null; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/AnnotatedTypeCachingTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.lang.reflect.Field; import java.util.Iterator; import java.util.Set; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class AnnotatedTypeCachingTest { @Test public void testAnnotatedTypeEqualityIgnoresContextualFields() { AnnotatedType type1 = new AnnotatedType(String.class) .propertyName("userStatus"); AnnotatedType type2 = new AnnotatedType(String.class) .propertyName("city"); assertEquals(type1, type2, "AnnotatedType objects with different contextual fields (e.g., propertyName) should be equal."); assertEquals(type1.hashCode(), type2.hashCode(), "The hash codes of equal AnnotatedType objects must be the same."); } static class User { public String username; public String email; public Address address; } static class Address { public String street; public String city; } private static class DummyModelConverter implements ModelConverter { @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { if (type.getType().equals(User.class)) { context.resolve(new AnnotatedType(String.class).propertyName("username")); context.resolve(new AnnotatedType(String.class).propertyName("email")); context.resolve(new AnnotatedType(Address.class).propertyName("address")); return new Schema(); } if (type.getType().equals(Address.class)) { context.resolve(new AnnotatedType(String.class).propertyName("street")); context.resolve(new AnnotatedType(String.class).propertyName("city")); return new Schema(); } return new Schema(); } } @Test @SuppressWarnings("unchecked") public void testCacheHitsForRepeatedStringTypeWithCorrectedEquals() throws Exception { ModelConverterContextImpl context = new ModelConverterContextImpl(new DummyModelConverter()); Schema userSchema = context.resolve(new AnnotatedType(User.class)); assertNotNull(userSchema); Field processedTypesField = ModelConverterContextImpl.class.getDeclaredField("processedTypes"); processedTypesField.setAccessible(true); Set processedTypes = (Set) processedTypesField.get(context); long stringTypeCount = processedTypes.stream() .filter(annotatedType -> annotatedType.getType().equals(String.class)) .count(); assertEquals(stringTypeCount, 1, "With the correct equals/hashCode, String type should be added to the cache only once."); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/AnnotatedTypeTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.AnnotatedType; import org.testng.annotations.Test; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Type; import java.util.HashSet; import java.util.Set; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertTrue; public class AnnotatedTypeTest { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface TestAnnA {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface TestAnnB {} @TestAnnA @TestAnnB @Deprecated private static class AnnotationHolder {} private Annotation getAnnotationInstance(Class clazz) { return AnnotationHolder.class.getAnnotation(clazz); } /** * Tests that equals() and hashCode() are order-insensitive for context annotations. */ @Test public void testEqualsAndHashCode_shouldBeOrderInsensitiveForAnnotations() { Annotation annA = getAnnotationInstance(TestAnnA.class); Annotation annB = getAnnotationInstance(TestAnnB.class); AnnotatedType type1 = new AnnotatedType(String.class).ctxAnnotations(new Annotation[]{annA, annB}); AnnotatedType type2 = new AnnotatedType(String.class).ctxAnnotations(new Annotation[]{annB, annA}); assertEquals(type1, type2, "Objects should be equal even if annotation order is different."); assertEquals(type1.hashCode(), type2.hashCode(), "Hash codes should be equal even if annotation order is different."); } /** * Tests that JDK/internal annotations are filtered out for equals() and hashCode() comparison. */ @Test public void testEqualsAndHashCode_shouldIgnoreJdkInternalAnnotations() { Annotation annA = getAnnotationInstance(TestAnnA.class); Annotation deprecated = getAnnotationInstance(Deprecated.class); AnnotatedType typeWithUserAnn = new AnnotatedType(String.class).ctxAnnotations(new Annotation[]{annA}); AnnotatedType typeWithJdkAnn = new AnnotatedType(String.class).ctxAnnotations(new Annotation[]{annA, deprecated}); AnnotatedType typeWithOnlyJdkAnn = new AnnotatedType(String.class).ctxAnnotations(new Annotation[]{deprecated}); AnnotatedType typeWithNoAnn = new AnnotatedType(String.class); assertEquals(typeWithUserAnn, typeWithJdkAnn, "JDK annotations should be ignored in equality comparison."); assertEquals(typeWithUserAnn.hashCode(), typeWithJdkAnn.hashCode(), "JDK annotations should be ignored in hashCode calculation."); assertEquals(typeWithOnlyJdkAnn, typeWithNoAnn, "An object with only JDK annotations should be equal to one with no annotations."); assertEquals(typeWithOnlyJdkAnn.hashCode(), typeWithNoAnn.hashCode(), "The hash code of an object with only JDK annotations should be the same as one with no annotations."); } /** * Tests that defensive copying prevents Set corruption from external array mutation. */ @Test public void testImmutability_shouldPreventCorruptionInHashSet() { Annotation annA = getAnnotationInstance(TestAnnA.class); Annotation annB = getAnnotationInstance(TestAnnB.class); Annotation[] originalAnnotations = new Annotation[]{annA}; AnnotatedType type = new AnnotatedType(String.class).ctxAnnotations(originalAnnotations); Set typeSet = new HashSet<>(); typeSet.add(type); int initialHashCode = type.hashCode(); originalAnnotations[0] = annB; assertEquals(initialHashCode, type.hashCode(), "Hash code must remain the same after mutating the external array."); assertTrue(typeSet.contains(type), "The Set must still contain the object after mutating the external array."); } /** * Tests that an instance of a subclass can be equal to an instance of the parent class. */ @Test public void testEqualsAndHashCode_shouldAllowSubclassEquality() { class SubAnnotatedType extends AnnotatedType { public SubAnnotatedType(Type type) { super(type); } } Annotation annA = getAnnotationInstance(TestAnnA.class); Annotation[] annotations = {annA}; AnnotatedType parent = new AnnotatedType(Integer.class).ctxAnnotations(annotations).name("number"); SubAnnotatedType child = new SubAnnotatedType(Integer.class); child.ctxAnnotations(annotations); child.name("number"); AnnotatedType differentParent = new AnnotatedType(Long.class).name("number"); assertEquals(parent, child, "Parent and child objects should be equal if their properties are the same."); assertEquals(child, parent, "Equality comparison should be symmetric."); assertEquals(parent.hashCode(), child.hashCode(), "Parent and child hash codes should be equal if their properties are the same."); assertNotEquals(parent, differentParent, "Objects with different properties should not be equal."); } @Test public void testEquals_shouldDifferentiatePropertyAndSubtypeContexts() { AnnotatedType typeAsProperty = new AnnotatedType(String.class) .schemaProperty(false) .propertyName("fieldA"); AnnotatedType typeAsSubtype = new AnnotatedType(String.class) .schemaProperty(true) .propertyName(null); assertNotEquals(typeAsProperty, typeAsSubtype, "Objects with different schemaProperty flags must not be equal."); assertNotEquals(typeAsProperty.hashCode(), typeAsSubtype.hashCode(), "Hash codes must be different if schemaProperty flags differ."); } @Test public void testEquals_shouldComparePropertyNameWhenSchemaPropertyIsTrue() { AnnotatedType complexPropA = new AnnotatedType(String.class) .schemaProperty(true) .propertyName("fieldA"); AnnotatedType complexPropB = new AnnotatedType(String.class) .schemaProperty(true) .propertyName("fieldB"); assertNotEquals(complexPropA, complexPropB, "When schemaProperty is true, objects with different propertyNames must not be equal."); assertNotEquals(complexPropA.hashCode(), complexPropB.hashCode(), "When schemaProperty is true, hash codes must be different if propertyNames differ."); } @Test public void testEquals_shouldBeEqualWhenSchemaPropertyIsTrueAndNamesMatch() { AnnotatedType complexPropA = new AnnotatedType(String.class) .schemaProperty(true) .propertyName("fieldA"); AnnotatedType complexPropC = new AnnotatedType(String.class) .schemaProperty(true) .propertyName("fieldA"); assertEquals(complexPropA, complexPropC, "When schemaProperty is true, objects with the same propertyName must be equal."); assertEquals(complexPropA.hashCode(), complexPropC.hashCode(), "When schemaProperty is true, hash codes must be equal if propertyNames are the same."); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ArrayOfSubclassTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.core.oas.models.ModelWithArrayOfSubclasses; import io.swagger.v3.core.util.Json31; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import org.testng.annotations.Test; import java.nio.file.Files; import java.nio.file.Paths; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.JsonNode; public class ArrayOfSubclassTest { @Test public void extractSubclassArray_oas31() throws Exception { ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema(ModelWithArrayOfSubclasses.Holder.class); assertNotNull(schema); String expectedJson = new String(Files.readAllBytes(Paths.get("src/test/resources/converting/ArrayOfSubclassTest_expected31.json"))); String actualJson = Json31.pretty(schema); ObjectMapper mapper = new ObjectMapper(); JsonNode expectedNode = mapper.readTree(expectedJson); JsonNode actualNode = mapper.readTree(actualJson); assertEquals(actualNode, expectedNode); } @Test public void extractSubclassArray_oas30() throws Exception { ResolvedSchema schema = ModelConverters.getInstance(false).readAllAsResolvedSchema(ModelWithArrayOfSubclasses.Holder.class); assertNotNull(schema); String expectedJson = new String(Files.readAllBytes(Paths.get("src/test/resources/converting/ArrayOfSubclassTest_expected30.json"))); String actualJson = Json31.pretty(schema); ObjectMapper mapper = new ObjectMapper(); JsonNode expectedNode = mapper.readTree(expectedJson); JsonNode actualNode = mapper.readTree(actualJson); assertEquals(actualNode, expectedNode); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ByteConverterTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.BinarySchema; import io.swagger.v3.oas.models.media.ByteArraySchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class ByteConverterTest { private static final String NEWLINE = System.getProperty("line.separator"); @Test public void testByte() { final Map models = ModelConverters.getInstance().read(ByteConverterModel.class); final String json = "{" + " \"ByteConverterModel\":{" + " \"type\":\"object\"," + " \"properties\":{" + " \"myBytes\":{" + " \"type\":\"array\"," + " \"items\":{" + " \"type\":\"string\"," + " \"format\":\"byte\"" + " }" + " }" + " }" + " }" + "}"; SerializationMatchers.assertEqualsToJson(models, json); } @Test public void testByteProperty() { Schema model = new Schema() .addProperties("byteProperty", new ByteArraySchema()); assertEquals(Json.pretty(model), "{" + NEWLINE + " \"properties\" : {" + NEWLINE + " \"byteProperty\" : {" + NEWLINE + " \"type\" : \"string\"," + NEWLINE + " \"format\" : \"byte\"" + NEWLINE + " }" + NEWLINE + " }" + NEWLINE + "}"); } @Test public void testDeserializeByteProperty() throws Exception { String json = "{\n" + " \"properties\" : {\n" + " \"byteProperty\" : {\n" + " \"type\" : \"string\",\n" + " \"format\" : \"byte\"\n" + " }\n" + " }\n" + "}"; Schema model = Json.mapper().readValue(json, Schema.class); assertNotNull(model); } @Test public void testByteArray() { Schema model = new Schema() .addProperties("byteArray", new ArraySchema().items(new BinarySchema())); assertEquals(Json.pretty(model), "{" + NEWLINE + " \"properties\" : {" + NEWLINE + " \"byteArray\" : {" + NEWLINE + " \"type\" : \"array\"," + NEWLINE + " \"items\" : {" + NEWLINE + " \"type\" : \"string\"," + NEWLINE + " \"format\" : \"binary\"" + NEWLINE + " }" + NEWLINE + " }" + NEWLINE + " }" + NEWLINE + "}"); } @Test public void testReadOnlyByteArray() { Schema model = new Schema() .addProperties("byteArray", new ArraySchema().items(new BinarySchema()).readOnly(true)); assertEquals(Json.pretty(model), "{" + NEWLINE + " \"properties\" : {" + NEWLINE + " \"byteArray\" : {" + NEWLINE + " \"type\" : \"array\"," + NEWLINE + " \"readOnly\" : true," + NEWLINE + " \"items\" : {" + NEWLINE + " \"type\" : \"string\"," + NEWLINE + " \"format\" : \"binary\"" + NEWLINE + " }" + NEWLINE + " }" + NEWLINE + " }" + NEWLINE + "}"); } class ByteConverterModel { public Byte[] myBytes = new Byte[0]; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/CompositionTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.oas.models.composition.AbstractBaseModelWithoutFields; import io.swagger.v3.core.oas.models.composition.Animal; import io.swagger.v3.core.oas.models.composition.AnimalClass; import io.swagger.v3.core.oas.models.composition.AnimalWithSchemaSubtypes; import io.swagger.v3.core.oas.models.composition.Human; import io.swagger.v3.core.oas.models.composition.ModelWithFieldWithSubTypes; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.io.IOException; import java.util.Map; public class CompositionTest { @Test(description = "read a model with required params and description") public void readModelWithRequiredParams() throws IOException { compareAsJson(Human.class, "Human.json"); } @Test(description = "read a model with composition") public void readModelWithComposition() throws IOException { compareAsJson(Animal.class, "Animal.json"); } @Test(description = "read a model with composition") public void readModeWithSchemalWithComposition() throws IOException { compareAsJson(AnimalWithSchemaSubtypes.class, "AnimalWithSchemaSubtypes.json"); } @Test(description = "read a model with composition") public void readClassModelWithComposition() throws IOException { compareAsJson(AnimalClass.class, "AnimalClass.json"); } @Test(description = "create a model") public void createModel() throws IOException { compareAsJson(AbstractBaseModelWithoutFields.class, "AbstractBaseModelWithoutFields.json"); } @Test(description = "create a ModelWithFieldWithSubTypes") public void createModelWithFieldWithSubTypes() throws IOException { compareAsJson(ModelWithFieldWithSubTypes.class, "ModelWithFieldWithSubTypes.json"); } private void compareAsJson(Class cls, String fileName) throws IOException { final Map schemas = ModelConverters.getInstance().readAll(cls); Json.prettyPrint(schemas); final String json = ResourceUtils.loadClassResource(getClass(), fileName); SerializationMatchers.assertEqualsToJson(schemas, json); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/CovariantGetterTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.oas.models.JCovariantGetter; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; public class CovariantGetterTest { @Test(description = "it should read a getter with covariant return type") public void testCovariantGetter() { final Map models = ModelConverters.getInstance().read(JCovariantGetter.Sub.class); assertEquals(models.size(), 1); final String json = "{" + " \"Sub\":{" + " \"type\":\"object\"," + " \"properties\":{" + " \"myProperty\":{" + " \"type\":\"integer\"," + " \"format\":\"int32\"" + " }," + " \"myOtherProperty\":{" + " \"type\":\"integer\"," + " \"format\":\"int32\"" + " }" + " }" + " }" + "}"; SerializationMatchers.assertEqualsToJson(models, json); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/EnumPropertyTest.java ================================================ package io.swagger.v3.core.converting; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.jackson.TypeNameResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.oas.models.Model1979; import io.swagger.v3.core.oas.models.ModelWithEnumField; import io.swagger.v3.core.oas.models.ModelWithEnumProperty; import io.swagger.v3.core.oas.models.ModelWithEnumRefProperty; import io.swagger.v3.core.oas.models.ModelWithJacksonEnumField; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Arrays; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class EnumPropertyTest { private ModelResolver modelResolver; private ModelConverterContextImpl context; @BeforeMethod public void setup() { ModelResolver.enumsAsRef = false; modelResolver = new ModelResolver(new ObjectMapper()); context = new ModelConverterContextImpl(modelResolver); } @AfterTest public void afterTest() { ModelResolver.enumsAsRef = false; } @Test(description = "it should read a model with an enum property") public void testEnumProperty() { final Map models = ModelConverters.getInstance().read(ModelWithEnumProperty.class); final String json = "{" + " \"ModelWithEnumProperty\":{" + " \"type\":\"object\"," + " \"properties\":{" + " \"enumValue\":{" + " \"type\":\"string\"," + " \"enum\":[" + " \"PRIVATE\"," + " \"PUBLIC\"," + " \"SYSTEM\"," + " \"INVITE_ONLY\"" + " ]" + " }" + " }" + " }" + "}"; SerializationMatchers.assertEqualsToJson(models, json); } @Test(description = "it should extract enum values from fields") public void testExtractEnumFields() { final Map models = ModelConverters.getInstance().read(ModelWithEnumField.class); final Schema model = models.get("ModelWithEnumField"); final Schema enumProperty = (Schema) model.getProperties().get("enumValue"); assertTrue(enumProperty instanceof StringSchema); final StringSchema stringProperty = (StringSchema) enumProperty; assertEquals(stringProperty.getEnum(), Arrays.asList("PRIVATE", "PUBLIC", "SYSTEM", "INVITE_ONLY")); } @Test(description = "it should extract enum values from method return types") public void testExtractEnumReturnType() { final Map models = ModelConverters.getInstance().read(ModelWithEnumProperty.class); final Schema model = models.get("ModelWithEnumProperty"); final Schema enumProperty = (Schema) model.getProperties().get("enumValue"); assertTrue(enumProperty instanceof StringSchema); final StringSchema stringProperty = (StringSchema) enumProperty; assertEquals(stringProperty.getEnum(), Arrays.asList("PRIVATE", "PUBLIC", "SYSTEM", "INVITE_ONLY")); } @Test(description = "it should read a model with an enum property as a reference") public void testEnumRefProperty() { Schema schema = context.resolve(new AnnotatedType(ModelWithEnumRefProperty.class)); final Map models = context.getDefinedModels(); final String yaml = "ModelWithEnumRefProperty:\n" + " type: object\n" + " properties:\n" + " a:\n" + " $ref: \"#/components/schemas/TestEnum\"\n" + " b:\n" + " $ref: \"#/components/schemas/TestEnum\"\n" + " c:\n" + " $ref: \"#/components/schemas/TestSecondEnum\"\n" + " d:\n" + " type: string\n" + " enum:\n" + " - A_PRIVATE\n" + " - A_PUBLIC\n" + " - A_SYSTEM\n" + " - A_INVITE_ONLY\n" + "TestEnum:\n" + " type: string\n" + " enum:\n" + " - PRIVATE\n" + " - PUBLIC\n" + " - SYSTEM\n" + " - INVITE_ONLY\n" + "TestSecondEnum:\n" + " type: string\n" + " enum:\n" + " - A_PRIVATE\n" + " - A_PUBLIC\n" + " - A_SYSTEM\n" + " - A_INVITE_ONLY\n"; SerializationMatchers.assertEqualsToYaml(models, yaml); } @Test(description = "it should read a model with an enum property as a reference with fqn TypeNameResolver") public void testEnumRefPropertyWithFQNTypeNameResolver() { TypeNameResolver.std.setUseFqn(true); Schema schema = context.resolve(new AnnotatedType(ModelWithEnumRefProperty.class)); final Map models = context.getDefinedModels(); final String yaml = "io.swagger.v3.core.oas.models.ModelWithEnumRefProperty:\n" + " type: object\n" + " properties:\n" + " a:\n" + " $ref: \"#/components/schemas/io.swagger.v3.core.oas.models.TestEnum\"\n" + " b:\n" + " $ref: \"#/components/schemas/io.swagger.v3.core.oas.models.TestEnum\"\n" + " c:\n" + " $ref: \"#/components/schemas/io.swagger.v3.core.oas.models.TestSecondEnum\"\n" + " d:\n" + " type: string\n" + " enum:\n" + " - A_PRIVATE\n" + " - A_PUBLIC\n" + " - A_SYSTEM\n" + " - A_INVITE_ONLY\n" + "io.swagger.v3.core.oas.models.TestEnum:\n" + " type: string\n" + " enum:\n" + " - PRIVATE\n" + " - PUBLIC\n" + " - SYSTEM\n" + " - INVITE_ONLY\n" + "io.swagger.v3.core.oas.models.TestSecondEnum:\n" + " type: string\n" + " enum:\n" + " - A_PRIVATE\n" + " - A_PUBLIC\n" + " - A_SYSTEM\n" + " - A_INVITE_ONLY\n"; TypeNameResolver.std.setUseFqn(false); SerializationMatchers.assertEqualsToYaml(models, yaml); } @Test(description = "it should read a model with an enum property as a reference, set via static var or sys prop") public void testEnumRefPropertyGlobal() { ModelResolver.enumsAsRef = true; Schema schema = context.resolve(new AnnotatedType(ModelWithEnumProperty.class)); final Map models = context.getDefinedModels(); final String yaml = "ModelWithEnumProperty:\n" + " type: object\n" + " properties:\n" + " enumValue:\n" + " $ref: \"#/components/schemas/TestEnum\"\n" + "TestEnum:\n" + " type: string\n" + " enum:\n" + " - PRIVATE\n" + " - PUBLIC\n" + " - SYSTEM\n" + " - INVITE_ONLY\n"; SerializationMatchers.assertEqualsToYaml(models, yaml); ModelResolver.enumsAsRef = false; } @Test(description = "it should not affect non-enum models when the enumsAsRef property is enabled globally") public void testEnumRefPropertyGlobalNotAffectingNonEnums() { ModelResolver.enumsAsRef = true; Schema schema = context.resolve(new AnnotatedType(Model1979.class)); final Map models = context.getDefinedModels(); final String yaml = "Model1979:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " nullable: true"; SerializationMatchers.assertEqualsToYaml(models, yaml); ModelResolver.enumsAsRef = false; } @Test(description = "it should extract enum values from fields using JsonProperty and JsonValue") public void testExtractJacksonEnumFields() { final Map models = ModelConverters.getInstance().read(ModelWithJacksonEnumField.class); final Schema model = models.get("ModelWithJacksonEnumField"); final Schema firstEnumProperty = (Schema) model.getProperties().get("firstEnumValue"); assertTrue(firstEnumProperty instanceof StringSchema); final StringSchema stringProperty = (StringSchema) firstEnumProperty; assertEquals(stringProperty.getEnum(), Arrays.asList("p1", "p2", "SYSTEM", "INVITE_ONLY")); final Schema secondEnumProperty = (Schema) model.getProperties().get("secondEnumValue"); assertTrue(secondEnumProperty instanceof StringSchema); final StringSchema secondStringProperty = (StringSchema) secondEnumProperty; assertEquals(secondStringProperty.getEnum(), Arrays.asList("one", "two", "three")); final Schema thirdEnumProperty = (Schema) model.getProperties().get("thirdEnumValue"); assertTrue(thirdEnumProperty instanceof IntegerSchema); final IntegerSchema thirdStringProperty = (IntegerSchema) thirdEnumProperty; assertEquals(thirdStringProperty.getEnum(), Arrays.asList(2, 4, 6)); final Schema fourthEnumProperty = (Schema) model.getProperties().get("fourthEnumValue"); assertTrue(fourthEnumProperty instanceof StringSchema); final StringSchema fourthStringProperty = (StringSchema) fourthEnumProperty; assertEquals(fourthStringProperty.getEnum(), Arrays.asList("one", "two", "three")); final Schema fifthEnumProperty = (Schema) model.getProperties().get("fifthEnumValue"); assertTrue(fifthEnumProperty instanceof IntegerSchema); final IntegerSchema fifthStringProperty = (IntegerSchema) fifthEnumProperty; assertEquals(fifthStringProperty.getEnum(), Arrays.asList(2, 4, 6)); final Schema sixthEnumProperty = (Schema) model.getProperties().get("sixthEnumValue"); assertTrue(sixthEnumProperty instanceof StringSchema); final StringSchema sixthStringProperty = (StringSchema) sixthEnumProperty; assertEquals(sixthStringProperty.getEnum(), Arrays.asList("one", "two", "three")); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/GuavaTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.oas.models.GuavaModel; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.io.IOException; import java.util.Map; public class GuavaTest { @Test(description = "convert a model with Guava optionals") public void convertModelWithGuavaOptionals() throws IOException { final Map schemas = ModelConverters.getInstance().read(GuavaModel.class); final String json = ResourceUtils.loadClassResource(getClass(), "GuavaTestModel.json"); SerializationMatchers.assertEqualsToJson(schemas, json); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/Issue5055Test.java ================================================ package io.swagger.v3.core.converting; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.core.util.Json31; import io.swagger.v3.oas.annotations.media.ArraySchema; import org.testng.annotations.Test; import java.util.List; import static org.testng.Assert.*; /** * test documenting the behavior of sibling @Schema and @ArraySchema annotations. */ public class Issue5055Test { @Test public void testArrayMetadataDoesNotLeakToItemsRef() throws Exception { ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema( TestModels.ArrayWithFullMetadata.class ); assertNotNull(schema, "Schema should resolve"); String json = Json31.pretty(schema); assertNotNull(json); ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(json); JsonNode itemsProp = root.at("/schema/properties/pets"); assertFalse(itemsProp.isMissingNode(), "pets property should exist"); assertEquals(itemsProp.get("type").asText(), "array", "Should be array type"); assertEquals(itemsProp.get("description").asText(), "Collection of pets", "Array should have description"); assertEquals(itemsProp.get("minItems").asInt(), 1, "Array should have minItems"); assertEquals(itemsProp.get("maxItems").asInt(), 100, "Array should have maxItems"); assertTrue(itemsProp.get("uniqueItems").asBoolean(), "Array should have uniqueItems"); JsonNode items = itemsProp.get("items"); assertNotNull(items, "Items should exist"); assertTrue(items.has("$ref"), "Items should be a reference"); assertFalse(items.has("minItems"), "BUG: minItems leaked to items $ref"); assertFalse(items.has("maxItems"), "BUG: maxItems leaked to items $ref"); assertFalse(items.has("uniqueItems"), "BUG: uniqueItems leaked to items $ref"); assertFalse(items.has("description") && items.get("description") != null, "BUG: array description leaked to items $ref"); if (items.has("type")) { assertTrue(items.get("type").isNull() || items.get("type").asText().isEmpty(), "BUG: type value leaked to items $ref"); } } @Test public void testComponentSchemaIsCleanWithoutLeakedProperties() throws Exception { ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema( TestModels.ArrayWithFullMetadata.class ); assertNotNull(schema); assertNotNull(schema.referencedSchemas); io.swagger.v3.oas.models.media.Schema petSchema = schema.referencedSchemas.get("Pet"); assertNotNull(petSchema, "Pet component schema should exist"); assertNull(petSchema.getMinItems(), "Component schema should not have minItems"); assertNull(petSchema.getMaxItems(), "Component schema should not have maxItems"); assertNull(petSchema.getUniqueItems(), "Component schema should not have uniqueItems"); if (petSchema.getDescription() != null) { assertNotEquals(petSchema.getDescription(), "Collection of pets", "Component should not have array's description"); } } @Test public void testArraySchemaAttributesSeparation() throws Exception { ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema( TestModels.BothArraySchemaAttributes.class ); assertNotNull(schema); String json = Json31.pretty(schema); ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(json); JsonNode dataField = root.at("/schema/properties/data"); if (!dataField.isMissingNode()) { assertTrue(dataField.has("description")); assertEquals(dataField.get("type").asText(), "array"); JsonNode items = dataField.get("items"); assertNotNull(items); assertTrue(items.has("description") || items.has("$ref")); } } @Test public void testTypeInferenceWithNoImplementation() throws Exception { ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema( TestModels.NoImplementationSpecified.class ); assertNotNull(schema); String json = Json31.pretty(schema); System.out.println("\n=== testTypeInferenceWithNoImplementation - Generated Spec ==="); System.out.println(json); System.out.println("=== End Spec ===\n"); ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(json); JsonNode dataField = root.at("/schema/properties/data"); assertEquals(dataField.get("type").asText(), "array"); JsonNode items = dataField.get("items"); assertNotNull(items); if (items.has("type")) { assertEquals(items.get("type").asText(), "string"); } } @Test public void testSchemaEqualsSemanticsForPrecedence() { io.swagger.v3.oas.models.media.Schema unchanged = new io.swagger.v3.oas.models.media.Schema(); unchanged.setType("array"); io.swagger.v3.oas.models.media.Schema alsoUnchanged = new io.swagger.v3.oas.models.media.Schema(); alsoUnchanged.setType("array"); assertEquals(unchanged, alsoUnchanged, "Equal content should be detected"); io.swagger.v3.oas.models.media.Schema changed = new io.swagger.v3.oas.models.media.Schema(); changed.setType("array"); changed.setDescription("added"); assertNotEquals(unchanged, changed, "Changes should be detected by equals"); } @Test public void testSchemaEqualsIncludesExtensions() { io.swagger.v3.oas.models.media.Schema s1 = new io.swagger.v3.oas.models.media.Schema(); s1.addExtension("x-prop", "value"); io.swagger.v3.oas.models.media.Schema s2 = new io.swagger.v3.oas.models.media.Schema(); s2.addExtension("x-prop", "value"); assertEquals(s1, s2, "Same extensions should be equal"); io.swagger.v3.oas.models.media.Schema s3 = new io.swagger.v3.oas.models.media.Schema(); s3.addExtension("x-prop", "different"); assertNotEquals(s1, s3, "Different extensions should not be equal"); } @Test public void testNoImplementationCase() throws Exception { ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema( TestModels.NoImplementationSpecified.class ); assertNotNull(schema); String json = Json31.pretty(schema); ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(json); JsonNode dataField = root.at("/schema/properties/data"); assertFalse(dataField.isMissingNode(), "data property should exist"); assertEquals(dataField.get("type").asText(), "array"); assertEquals(dataField.get("description").asText(), "Inferred from type"); JsonNode items = dataField.get("items"); assertNotNull(items); assertEquals(items.get("type").asText(), "string", "Items should infer string type"); } @Test public void testNoSchemaAtAllCase() throws Exception { ResolvedSchema schema = ModelConverters.getInstance(true).readAllAsResolvedSchema( TestModels.NoSchemaAnnotations.class ); assertNotNull(schema); String json = Json31.pretty(schema); ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(json); JsonNode dataField = root.at("/schema/properties/data"); assertFalse(dataField.isMissingNode(), "data property should exist"); assertEquals(dataField.get("type").asText(), "array"); JsonNode items = dataField.get("items"); assertNotNull(items); assertEquals(items.get("type").asText(), "string", "Items should infer string type from List"); } public static class TestModels { @io.swagger.v3.oas.annotations.media.Schema(description = "Model with full array metadata") public static class ArrayWithFullMetadata { private List pets; @ArraySchema( schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = Pet.class), arraySchema = @io.swagger.v3.oas.annotations.media.Schema( type = "array", description = "Collection of pets" ), minItems = 1, maxItems = 100, uniqueItems = true ) public List getPets() { return pets; } } @io.swagger.v3.oas.annotations.media.Schema(description = "Pet model") public static class Pet { private String name; private String species; public String getName() { return name; } public String getSpecies() { return species; } } @io.swagger.v3.oas.annotations.media.Schema(description = "Test precedence") public static class SchemaTakesPrecedence { private List data; @io.swagger.v3.oas.annotations.media.Schema(type = "array", description = "Schema description") @ArraySchema(minItems = 10) public List getData() { return data; } } @io.swagger.v3.oas.annotations.media.Schema(description = "Test both attributes") public static class BothArraySchemaAttributes { private List data; @ArraySchema( schema = @io.swagger.v3.oas.annotations.media.Schema(type = "string", description = "Item description"), arraySchema = @io.swagger.v3.oas.annotations.media.Schema(type = "array", description = "Array description") ) public List getData() { return data; } } @io.swagger.v3.oas.annotations.media.Schema(description = "Test no implementation") public static class NoImplementationSpecified { private List data; @io.swagger.v3.oas.annotations.media.Schema(description = "Inferred from type") public List getData() { return data; } } @io.swagger.v3.oas.annotations.media.Schema(description = "Test no schema annotations") public static class NoSchemaAnnotations { private List data; public List getData() { return data; } } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelConverterTest.java ================================================ package io.swagger.v3.core.converting; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.google.common.collect.ImmutableSet; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.oas.models.Cat; import io.swagger.v3.core.oas.models.ClientOptInput; import io.swagger.v3.core.oas.models.Employee; import io.swagger.v3.core.oas.models.EmptyModel; import io.swagger.v3.core.oas.models.JacksonReadonlyModel; import io.swagger.v3.core.oas.models.JodaDateTimeModel; import io.swagger.v3.core.oas.models.Model1155; import io.swagger.v3.core.oas.models.ModelPropertyName; import io.swagger.v3.core.oas.models.ModelWithAltPropertyName; import io.swagger.v3.core.oas.models.ModelWithApiModel; import io.swagger.v3.core.oas.models.ModelWithEnumArray; import io.swagger.v3.core.oas.models.ModelWithFormattedStrings; import io.swagger.v3.core.oas.models.ModelWithNumbers; import io.swagger.v3.core.oas.models.ModelWithOffset; import io.swagger.v3.core.oas.models.ModelWithTuple2; import io.swagger.v3.core.oas.models.Person; import io.swagger.v3.core.oas.models.composition.AbstractModelWithApiModel; import io.swagger.v3.core.oas.models.composition.ModelWithUrlProperty; import io.swagger.v3.core.oas.models.composition.Pet; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.MapSchema; import io.swagger.v3.oas.models.media.NumberSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Ignore; import org.testng.annotations.Test; import java.io.IOException; import java.lang.reflect.Type; import java.net.URI; import java.net.URL; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.Map; import java.util.TreeSet; import java.util.UUID; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; public class ModelConverterTest { private Map read(Type type) { return ModelConverters.getInstance().read(type); } private Map readAll(Type type) { return ModelConverters.getInstance().readAll(type); } private void assertEqualsToJson(Object objectToSerialize, String fileName) throws IOException { final String json = ResourceUtils.loadClassResource(getClass(), fileName); SerializationMatchers.assertEqualsToJson(objectToSerialize, json); } @Test(description = "it should convert a model") public void convertModel() throws IOException { assertEqualsToJson(read(Person.class), "Person.json"); } @Test(description = "it should convert a model with Joda DateTime") public void convertModelWithJodaDateTime() throws IOException { assertEqualsToJson(read(JodaDateTimeModel.class), "JodaDateTimeModel.json"); } @Test(description = "read an interface") public void readInterface() throws IOException { assertEqualsToJson(readAll(Pet.class), "Pet.json"); } @Test(description = "it should read an inherited interface") public void readInheritedInterface() throws IOException { assertEqualsToJson(readAll(Cat.class), "Cat.json"); } @Test(description = "it should honor the ApiModel name") public void honorApiModelName() { final Map schemas = readAll(ModelWithApiModel.class); assertEquals(schemas.size(), 1); String model = schemas.keySet().iterator().next(); assertEquals(model, "MyModel"); } @Test(description = "it should override an inherited model's name") public void overrideInheritedModelName() { final Map rootSchemas = readAll(AbstractModelWithApiModel.class); assertEquals(rootSchemas.size(), 3); assertTrue(rootSchemas.containsKey("MyProperty")); assertTrue(rootSchemas.containsKey("ModelWithUrlProperty")); assertTrue(rootSchemas.containsKey("ModelWithValueProperty")); final Map nestedSchemas = readAll(ModelWithUrlProperty.class); assertEquals(nestedSchemas.size(), 1); assertTrue(nestedSchemas.containsKey("ModelWithUrlProperty")); assertFalse(nestedSchemas.containsKey("MyProperties")); } @Test(description = "it should maintain property names") public void maintainPropertyNames() { final Map schemas = readAll(ModelPropertyName.class); assertEquals(schemas.size(), 1); final String modelName = schemas.keySet().iterator().next(); assertEquals(modelName, "ModelPropertyName"); final Schema model = schemas.get(modelName); final Iterator itr = new TreeSet(model.getProperties().keySet()).iterator(); assertEquals(itr.next(), "gettersAndHaters"); assertEquals(itr.next(), "is_persistent"); } @Test(description = "it should serialize a parameterized type per 606") public void serializeParameterizedType() { final Map schemas = readAll(Employee.class); final Schema employee = (Schema) schemas.get("employee").getProperties().get("employee"); final Map props = employee.getProperties(); final Iterator et = props.keySet().iterator(); final Schema id = props.get(et.next()); assertTrue(id instanceof IntegerSchema); final Schema firstName = props.get(et.next()); assertTrue(firstName instanceof StringSchema); final Schema lastName = props.get(et.next()); assertTrue(lastName instanceof StringSchema); final Schema department = props.get(et.next()); assertNotNull(department.get$ref()); final Schema manager = props.get(et.next()); assertNotNull(manager.get$ref()); final Schema team = props.get(et.next()); assertTrue(team instanceof ArraySchema); final ArraySchema ap = (ArraySchema) team; assertTrue(ap.getUniqueItems()); assertNotNull(employee.getXml()); assertEquals(employee.getXml().getName(), "employee"); } @Test(description = "it should ignore hidden fields") public void ignoreHiddenFields() { final Map schemas = readAll(ClientOptInput.class); final Schema model = schemas.get("ClientOptInput"); assertEquals(model.getProperties().size(), 2); } @Test(description = "it should set readOnly per #854") public void setReadOnly() { final Map schemas = readAll(JacksonReadonlyModel.class); final Schema model = (Schema) schemas.get("JacksonReadonlyModel"); final Schema prop = (Schema) model.getProperties().get("count"); assertTrue(prop.getReadOnly()); } @Test(description = "it should process a model with org.apache.commons.lang3.tuple.Pair properties") public void processModelWithPairProperties() { final ModelWithTuple2.TupleAsMapPropertyConverter asPropertyConverter = new ModelWithTuple2.TupleAsMapPropertyConverter(Json.mapper()); ModelConverters.getInstance().addConverter(asPropertyConverter); final Map asProperty = readAll(ModelWithTuple2.class); ModelConverters.getInstance().removeConverter(asPropertyConverter); Map values = asProperty.get("ModelWithTuple2").getProperties(); Yaml.prettyPrint(values); for (Map.Entry entry : values.entrySet()) { String name = entry.getKey(); Schema property = entry.getValue(); if ("timesheetStates".equals(name)) { assertEquals(property.getClass(), MapSchema.class); } else if ("manyPairs".equals(name)) { assertEquals(property.getClass(), ArraySchema.class); Schema items = ((ArraySchema) property).getItems(); assertNotNull(items); assertEquals(items.getClass(), MapSchema.class); Schema stringProperty = (Schema)((MapSchema) items).getAdditionalProperties(); assertNotNull(stringProperty); assertEquals(stringProperty.getClass(), StringSchema.class); } else if ("complexLeft".equals(name)) { assertEquals(property.getClass(), ArraySchema.class); Schema items = ((ArraySchema) property).getItems(); assertNotNull(items); assertEquals(items.getClass(), MapSchema.class); Schema additionalProperty = (Schema)((MapSchema) items).getAdditionalProperties(); assertNotNull(additionalProperty); assertNotNull(additionalProperty.get$ref()); assertEquals(additionalProperty.get$ref(), "#/components/schemas/ComplexLeft"); } else { fail(String.format("Unexpected property: %s", name)); } } } @Test(description = "it should scan an empty model per 499") public void scanEmptyModel() { final Map schemas = readAll(EmptyModel.class); final Schema model = (Schema) schemas.get("EmptyModel"); assertNull(model.getProperties()); assertEquals(model.getType(), "object"); } @Test(description = "it should override the property name") public void overridePropertyName() { final Map schemas = readAll(ModelWithAltPropertyName.class); final Map properties = schemas.get("sample_model").getProperties(); assertNull(properties.get("id")); assertNotNull(properties.get("the_id")); } @Test(description = "it should convert a model with enum array") public void convertModelWithEnumArray() { final Map schemas = readAll(ModelWithEnumArray.class); assertEquals(schemas.size(), 1); } private Type getGenericType(Class cls) throws Exception { return getClass().getDeclaredMethod("getGenericType", Class.class).getGenericParameterTypes()[0]; } @Test(description = "it should check handling of the Class type") public void checkHandlingClassType() throws Exception { final Type type = getGenericType(null); assertFalse(type instanceof Class); final Map schemas = readAll(type); assertEquals(schemas.size(), 0); } @Test(description = "it should convert a model with Formatted strings") public void convertModelWithFormattedStrings() throws IOException { final Schema model = readAll(ModelWithFormattedStrings.class).get("ModelWithFormattedStrings"); assertEqualsToJson(model, "ModelWithFormattedStrings.json"); } @Test(description = "it should check handling of string types") public void checkStringTypesHandling() { for (Class cls : Arrays.asList(URI.class, URL.class, UUID.class)) { final Map schemas = readAll(cls); assertEquals(schemas.size(), 0); final Schema property = ModelConverters.getInstance().readAllAsResolvedSchema(cls).schema; assertNotNull(property); assertEquals(property.getType(), "string"); } } @Test(description = "it should scan a model per #1155") public void scanModel() { final Map model = read(Model1155.class); assertEquals(model.get("Model1155").getProperties().keySet(), ImmutableSet.of("valid", "value", "is", "get", "isA", "getA", "is_persistent", "gettersAndHaters")); } @Test(description = "it should scan a model with numbers") public void scanModelWithNumbers() throws IOException { final Map models = readAll(ModelWithNumbers.class); assertEquals(models.size(), 1); final Schema model = models.get("ModelWithNumbers"); // Check if we get required properties after building models from classes. checkModel(model); // Check if we get required properties after deserialization from JSON checkModel(Json.mapper().readValue(Json.pretty(model), Schema.class)); } @Test(description = "it tests a model with java offset") public void scanModelWithOffset() throws IOException { final Map models = readAll(ModelWithOffset.class); assertEquals(models.size(), 1); final Schema model = models.get("ModelWithOffset"); Schema property = (Schema) model.getProperties().get("offset"); assertEquals(property.getType(), "string"); assertEquals(property.getFormat(), "date-time"); } private void checkType(Schema property, Class cls, String type, String format) { assertTrue(cls.isInstance(property)); assertEquals(property.getType(), type); if (format == null) { assertNull(property.getFormat()); } else { assertEquals(property.getFormat(), format); } } private void checkModel(Schema model) { Map props = model.getProperties(); for (Map.Entry entry : props.entrySet()) { final String name = entry.getKey(); final Schema property = entry.getValue(); if (Arrays.asList("shortPrimitive", "shortObject", "intPrimitive", "intObject").contains(name)) { checkType(property, IntegerSchema.class, "integer", "int32"); } else if (Arrays.asList("longPrimitive", "longObject").contains(name)) { checkType(property, IntegerSchema.class, "integer", "int64"); } else if (Arrays.asList("floatPrimitive", "floatObject").contains(name)) { checkType(property, NumberSchema.class, "number", "float"); } else if (Arrays.asList("doublePrimitive", "doubleObject").contains(name)) { checkType(property, NumberSchema.class, "number", "double"); } else if ("bigInteger".equals(name)) { checkType(property, IntegerSchema.class, "integer", null); } else if ("bigDecimal".equals(name)) { checkType(property, NumberSchema.class, "number", null); } else { fail(String.format("Unexpected property: %s", name)); } } } @Test public void formatDate() { final Map models = ModelConverters.getInstance().read(DateModel.class); final Schema model = models.get("DateModel"); assertEquals(model.getProperties().size(), 5); final String json = "{" + " \"type\":\"object\"," + " \"properties\":{" + " \"date\":{" + " \"type\":\"string\"," + " \"format\":\"date-time\"" + " }," + " \"intValue\":{" + " \"type\":\"integer\"," + " \"format\":\"int32\"" + " }," + " \"longValue\":{" + " \"type\":\"integer\"," + " \"format\":\"int64\"" + " }," + " \"floatValue\":{" + " \"type\":\"number\"," + " \"format\":\"float\"" + " }," + " \"doubleValue\":{" + " \"type\":\"number\"," + " \"format\":\"double\"" + " }" + " }" + "}"; SerializationMatchers.assertEqualsToJson(model, json); } class DateModel { @io.swagger.v3.oas.annotations.media.Schema public Date date; @io.swagger.v3.oas.annotations.media.Schema public int intValue; @io.swagger.v3.oas.annotations.media.Schema public Long longValue; @io.swagger.v3.oas.annotations.media.Schema public Float floatValue; @io.swagger.v3.oas.annotations.media.Schema public Double doubleValue; } @Test public void indirectPropertiesRecognized() { final Map models = ModelConverters.getInstance().read(BaseClass.class); final Schema model = models.get("BaseClass"); assertNotNull(model); assertEquals(model.getName(), "BaseClass"); assertNotNull(model.getProperties()); assertEquals(model.getProperties().size(), 1); } @Test public void checkDefaultSkippedPackages(){ ModelConverters modelConverters = ModelConverters.getInstance(); assertTrue(modelConverters.getSkippedPackages().contains("java.lang")); assertTrue(modelConverters.getSkippedPackages().contains("groovy.lang")); } @Test(description = "It should not process skipped package") public void ignoreSkippedPackage() throws ClassNotFoundException { ModelConverters modelConverters = ModelConverters.getInstance(); final Type type = Class.forName("java.lang.String"); assertNull(modelConverters.readAllAsResolvedSchema(type)); } @JsonSerialize(as = AnnotatedImplementationClass.class) abstract class BaseClass { public abstract String field(); } class AnnotatedImplementationClass extends BaseClass { @Override @JsonProperty public String field() { return "value"; } } @Test @Ignore public void directPropertiesRecognized() { final Map models = ModelConverters.getInstance().read(AnnotatedBaseClass.class); final Schema model = models.get("AnnotatedBaseClass"); assertNotNull(model); assertEquals(model.getName(), "AnnotatedBaseClass"); assertNotNull(model.getProperties()); assertEquals(model.getProperties().size(), 1); } abstract class AnnotatedBaseClass { @JsonProperty public abstract String field(); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/ModelPropertyTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.oas.models.Model1979; import io.swagger.v3.core.oas.models.ModelWithBooleanProperty; import io.swagger.v3.core.oas.models.ModelWithModelPropertyOverrides; import io.swagger.v3.core.oas.models.ModelWithPrimitiveArray; import io.swagger.v3.core.oas.models.ReadOnlyFields; import io.swagger.v3.core.oas.models.RequiredFields; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.BooleanSchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class ModelPropertyTest { @Test public void extractProperties() { final Map models = ModelConverters.getInstance().readAll(Family.class); assertEquals(models.size(), 3); final Schema person = models.get("Person"); final Schema employer = (Schema) person.getProperties().get("employer"); assertTrue(employer instanceof ArraySchema); final ArraySchema employerProperty = (ArraySchema) employer; final Schema items = employerProperty.getItems(); assertEquals(items.get$ref(), "#/components/schemas/Employer"); final Schema awards = (Schema) person.getProperties().get("awards"); assertTrue(awards instanceof ArraySchema); assertTrue(((ArraySchema) awards).getItems() instanceof StringSchema); } @Test public void extractPrimitiveArray() { final Map models = ModelConverters.getInstance().readAll(ModelWithPrimitiveArray.class); assertEquals(models.size(), 1); final Schema model = models.get("ModelWithPrimitiveArray"); final ArraySchema longArray = (ArraySchema) model.getProperties().get("longArray"); final Schema longArrayItems = longArray.getItems(); assertTrue(longArrayItems instanceof IntegerSchema); final ArraySchema intArray = (ArraySchema) model.getProperties().get("intArray"); assertTrue(intArray.getItems() instanceof IntegerSchema); } @Test public void readModelProperty() { final Map models = ModelConverters.getInstance().readAll(IsModelTest.class); final Schema model = models.get("IsModelTest"); assertNotNull(model); } @Test(description = "it should read a model with property dataTypes configured #679") public void readDataTypesProperty() { final Map models = ModelConverters.getInstance().readAll(ModelWithModelPropertyOverrides.class); final String json = "{" + " \"Children\":{" + " \"type\":\"object\"," + " \"properties\":{" + " \"name\":{" + " \"type\":\"string\"" + " }" + " }" + " }," + " \"ModelWithModelPropertyOverrides\":{" + " \"type\":\"object\"," + " \"properties\":{" + " \"children\":{" + " \"type\":\"array\"," + " \"items\":{" + " \"$ref\":\"#/components/schemas/Children\"" + " }" + " }" + " }" + " }" + "}"; SerializationMatchers.assertEqualsToJson(models, json); } @Test public void testReadOnlyProperty() { final Map models = ModelConverters.getInstance().readAll(ReadOnlyFields.class); Schema model = models.get("ReadOnlyFields"); assertTrue(((Schema) model.getProperties().get("id")).getReadOnly()); } @Test public void testRequiredProperty() { final Map models = ModelConverters.getInstance().readAll(RequiredFields.class); Schema model = models.get("RequiredFields"); assertFalse(model.getRequired().contains("optionalField")); assertFalse(model.getRequired().contains("primitiveTypeWithoutConstraint")); assertTrue(model.getRequired().contains("primitiveTypeWithConstraint")); assertTrue(model.getRequired().contains("required")); assertFalse(model.getRequired().contains("notRequired")); assertTrue(model.getRequired().contains("notRequiredWithAnnotation")); assertFalse(model.getRequired().contains("modeAuto")); assertTrue(model.getRequired().contains("modeAutoWithAnnotation")); assertTrue(model.getRequired().contains("modeRequired")); assertFalse(model.getRequired().contains("modeNotRequired")); assertFalse(model.getRequired().contains("modeNotRequiredWithAnnotation")); assertFalse(model.getRequired().contains("modeNotRequiredWithAnnotationForNotBlank")); assertFalse(model.getRequired().contains("modeNotRequiredWithAnnotationForNotEmpty")); } @Test public void modelAllowEmptyTest() { final Map models = ModelConverters.getInstance().readAll(Model1979.class); Schema model = models.get("Model1979"); assertTrue(((Schema) model.getProperties().get("id")).getNullable()); } @Test public void testIssue1743() { final Map models = ModelConverters.getInstance().readAll(ModelWithBooleanProperty.class); final Schema model = models.get("ModelWithBooleanProperty"); assertNotNull(model); BooleanSchema bp = (BooleanSchema) model.getProperties().get("isGreat"); assertTrue(bp.getEnum().size() == 1); assertEquals(bp.getEnum().get(0), Boolean.TRUE); IntegerSchema is = (IntegerSchema) model.getProperties().get("intValue"); assertTrue(is.getEnum().size() == 2); assertEquals(is.getEnum().get(0), new Integer(1)); assertEquals(is.getEnum().get(1), new Integer(2)); } @Test public void testNotNullWithNotBlankAndNotEmpty() { final Map models = ModelConverters.getInstance().readAll(NotNullWithNotBlankNotEmptyModel.class); Schema model = models.get("NotNullWithNotBlankNotEmptyModel"); assertTrue(model.getRequired().contains("notNullAndNotBlank")); assertTrue(model.getRequired().contains("notNullAndNotEmptyList")); assertTrue(model.getRequired().contains("notNullAndNotEmptySet")); } @Test public void testCollectionWithNotEmpty() { final Map models = ModelConverters.getInstance().readAll(CollectionWithNotEmptyModel.class); Schema model = models.get("CollectionWithNotEmptyModel"); ArraySchema listSchema = (ArraySchema) model.getProperties().get("notEmptyList"); assertNotNull(listSchema); assertEquals(listSchema.getMinItems(), Integer.valueOf(1)); ArraySchema setSchema = (ArraySchema) model.getProperties().get("notEmptySet"); assertNotNull(setSchema); assertEquals(setSchema.getMinItems(), Integer.valueOf(1)); } @Test public void testStringWithNotBlankAndSize() { final Map models = ModelConverters.getInstance().readAll(StringWithNotBlankAndSizeModel.class); Schema model = models.get("StringWithNotBlankAndSizeModel"); Schema strSchema = (Schema) model.getProperties().get("notBlankAndSized"); assertNotNull(strSchema); assertEquals(strSchema.getMinLength(), Integer.valueOf(5)); assertEquals(strSchema.getMaxLength(), Integer.valueOf(10)); } @Test public void testNotBlankNotEmptyWithRequiredModeNotRequired() { final Map models = ModelConverters.getInstance().readAll(NotBlankNotEmptyWithRequiredModeNotRequiredModel.class); Schema model = models.get("NotBlankNotEmptyWithRequiredModeNotRequiredModel"); assertFalse(model.getRequired() != null && model.getRequired().contains("notBlankNotRequired")); assertFalse(model.getRequired() != null && model.getRequired().contains("notEmptyListNotRequired")); assertFalse(model.getRequired() != null && model.getRequired().contains("notEmptySetNotRequired")); // @NotBlank should generate minLength: 1 Schema notBlankSchema = (Schema) model.getProperties().get("notBlankNotRequired"); assertNotNull(notBlankSchema); assertEquals(notBlankSchema.getMinLength(), Integer.valueOf(1)); // @NotEmpty should generate minItems: 1 ArraySchema listSchema = (ArraySchema) model.getProperties().get("notEmptyListNotRequired"); assertNotNull(listSchema); assertEquals(listSchema.getMinItems(), Integer.valueOf(1)); ArraySchema setSchema = (ArraySchema) model.getProperties().get("notEmptySetNotRequired"); assertNotNull(setSchema); assertEquals(setSchema.getMinItems(), Integer.valueOf(1)); } @Test public void testNotBlankNotEmptyWithRequiredModeRequired() { final Map models = ModelConverters.getInstance().readAll(NotBlankNotEmptyWithRequiredModeRequiredModel.class); Schema model = models.get("NotBlankNotEmptyWithRequiredModeRequiredModel"); assertTrue(model.getRequired().contains("notBlankRequired")); assertTrue(model.getRequired().contains("notEmptyListRequired")); assertTrue(model.getRequired().contains("notEmptySetRequired")); // @NotBlank should generate minLength: 1 Schema notBlankSchema = (Schema) model.getProperties().get("notBlankRequired"); assertNotNull(notBlankSchema); assertEquals(notBlankSchema.getMinLength(), Integer.valueOf(1)); // @NotEmpty should generate minItems: 1 ArraySchema listSchema = (ArraySchema) model.getProperties().get("notEmptyListRequired"); assertNotNull(listSchema); assertEquals(listSchema.getMinItems(), Integer.valueOf(1)); ArraySchema setSchema = (ArraySchema) model.getProperties().get("notEmptySetRequired"); assertNotNull(setSchema); assertEquals(setSchema.getMinItems(), Integer.valueOf(1)); } class Family { public Date membersSince; public List members; } class Person { public String firstname; public String lastname; public int age; public Date birthday; public List employer; public List awards; } class Employer { public String name; public int size; } class IsModelTest { public Boolean is_happy; public String name; } static class NotNullWithNotBlankNotEmptyModel { @NotNull @NotBlank public String notNullAndNotBlank; @NotNull @NotEmpty public List notNullAndNotEmptyList; @NotNull @NotEmpty public Set notNullAndNotEmptySet; } static class CollectionWithNotEmptyModel { @NotEmpty public List notEmptyList; @NotEmpty public Set notEmptySet; } static class StringWithNotBlankAndSizeModel { @NotBlank @Size(min = 5, max = 10) public String notBlankAndSized; } static class NotBlankNotEmptyWithRequiredModeRequiredModel { @NotBlank @io.swagger.v3.oas.annotations.media.Schema(requiredMode = io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED) public String notBlankRequired; @NotEmpty @io.swagger.v3.oas.annotations.media.Schema(requiredMode = io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED) public List notEmptyListRequired; @NotEmpty @io.swagger.v3.oas.annotations.media.Schema(requiredMode = io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED) public Set notEmptySetRequired; } static class NotBlankNotEmptyWithRequiredModeNotRequiredModel { @NotBlank @io.swagger.v3.oas.annotations.media.Schema(requiredMode = io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED) public String notBlankNotRequired; @NotEmpty @io.swagger.v3.oas.annotations.media.Schema(requiredMode = io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED) public List notEmptyListNotRequired; @NotEmpty @io.swagger.v3.oas.annotations.media.Schema(requiredMode = io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED) public Set notEmptySetNotRequired; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/NumericFormatTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Min; import java.math.BigDecimal; import java.util.Map; import static io.swagger.v3.core.util.TestUtils.normalizeLineEnds; import static org.testng.Assert.assertEquals; public class NumericFormatTest { @Test public void testFormatOfInteger() { final Map models = ModelConverters.getInstance().readAll(ModelWithIntegerFields.class); assertEquals(models.size(), 1); String json = Json.pretty(models); assertEquals(normalizeLineEnds(json), "{\n" + " \"ModelWithIntegerFields\" : {\n" + " \"type\" : \"object\",\n" + " \"properties\" : {\n" + " \"id\" : {\n" + " \"minimum\" : 3,\n" + " \"type\" : \"integer\",\n" + " \"format\" : \"int32\"\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testFormatOfDecimal() { final Map models = ModelConverters.getInstance().readAll(ModelWithDecimalFields.class); assertEquals(models.size(), 1); String json = Json.pretty(models); assertEquals(normalizeLineEnds(json), "{\n" + " \"ModelWithDecimalFields\" : {\n" + " \"type\" : \"object\",\n" + " \"properties\" : {\n" + " \"id\" : {\n" + " \"minimum\" : 3.3,\n" + " \"exclusiveMinimum\" : false,\n" + " \"type\" : \"number\",\n" + " \"format\" : \"double\"\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testFormatOfBigDecimal() { final Map models = ModelConverters.getInstance().readAll(ModelWithoutScientificFields.class); assertEquals(models.size(), 1); String json = Json.pretty(models); assertEquals(normalizeLineEnds(json), "{\n" + " \"ModelWithoutScientificFields\" : {\n" + " \"type\" : \"object\",\n" + " \"properties\" : {\n" + " \"id\" : {\n" + " \"maximum\" : 9999999999999999.99,\n" + " \"exclusiveMaximum\" : false,\n" + " \"minimum\" : -9999999999999999.99,\n" + " \"exclusiveMinimum\" : false,\n" + " \"type\" : \"number\"\n" + " }\n" + " }\n" + " }\n" + "}"); } static class ModelWithIntegerFields { @io.swagger.v3.oas.annotations.media.Schema @Min(value = 3) public Integer id; } static class ModelWithDecimalFields { @io.swagger.v3.oas.annotations.media.Schema @DecimalMin(value = "3.3") public Double id; } static class ModelWithoutScientificFields { @io.swagger.v3.oas.annotations.media.Schema @DecimalMin(value = "-9999999999999999.99") @DecimalMax(value = "9999999999999999.99") public BigDecimal id; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/PojoTest.java ================================================ package io.swagger.v3.core.converting; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import org.testng.annotations.Test; import javax.validation.constraints.Pattern; import java.io.IOException; import java.lang.reflect.Type; import java.util.Date; import java.util.Map; import static org.testng.Assert.assertEquals; public class PojoTest { private Map read(Type type) { return ModelConverters.getInstance().read(type); } private Map readAll(Type type) { return ModelConverters.getInstance().readAll(type); } private void assertEqualsToJson(Object objectToSerialize, String fileName) throws IOException { final String json = ResourceUtils.loadClassResource(getClass(), fileName); SerializationMatchers.assertEqualsToJson(objectToSerialize, json); } @Test public void testModelWithTitle() { String yaml = "ClassWithTitle:\n" + " type: object\n" + " title: 'My Pojo'\n" + " properties:\n" + " id:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(read(ClassWithTitle.class), yaml); } @Schema(title = "My Pojo") static class ClassWithTitle { private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } } @Test(description = "The @Schema annotation will only be adding additional sugar on the property") public void testModelWithAnnotatedPrivateMember() { String yaml = "ClassWithAnnotatedProperty:\n" + " type: object\n" + " properties:\n" + " id:\n" + " description: 'a long description for this property'\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(read(ClassWithAnnotatedProperty.class), yaml); } static class ClassWithAnnotatedProperty { @Schema(description = "a long description for this property") private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } } @Test(description = "The @Schema annotation will only be adding additional sugar on the property") public void testModelWithAnnotatedPublicMethod() { String yaml = "ClassWithAnnotatedMethod:\n" + " type: object\n" + " properties:\n" + " id:\n" + " description: 'a long description for this property'\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(read(ClassWithAnnotatedMethod.class), yaml); } static class ClassWithAnnotatedMethod { private String id; @Schema(description = "a long description for this property") public String getId() { return id; } public void setId(String id) { this.id = id; } } @Test(description = "The @Schema annotation will override the type of the actual parameter") public void testModelWithOverriddenMemberType() { String yaml = "ClassWithOverriddenMemberType:\n" + " type: object\n" + " properties:\n" + " id:\n" + " description: 'we are declaring a string implementation must be a valid long integer, even though " + "the model backs it with a String implementation'\n" + " type: integer\n" + " format: int64"; SerializationMatchers.assertEqualsToYaml(read(ClassWithOverriddenMemberType.class), yaml); } static class ClassWithOverriddenMemberType { private String id; @Schema(type = "integer", format = "int64", description = "we are declaring a string implementation must be " + "a valid long integer, even though the model backs it with a String implementation") public String getId() { return id; } public void setId(String id) { this.id = id; } } @Test(description = "@Schema is completely overriding the type for this model") public void testModelWithAlternateRepresentation() { String yaml = "ClassWithAnnotatedMethod:\n" + " type: object\n" + " properties:\n" + " id:\n" + " description: 'a long description for this property'\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(read(ClassWithAlternateRepresentation.class), yaml); } @Schema(implementation = ClassWithAnnotatedMethod.class) static class ClassWithAlternateRepresentation { private Date dateField; public Date getDateField() { return dateField; } public void setDateField(Date dateField) { this.dateField = dateField; } } @Test(description = "@Schema is allowing multiple definition interfaces to represent this model") public void testModelWithMultipleRepresentations() { String yaml = "anyOf:\n" + "- $ref: \"#/components/schemas/UserObject\"\n" + "- $ref: \"#/components/schemas/EmployeeObject\"\n" + "type: object\n" + "properties:\n" + " id:\n" + " type: string\n" + " format: uuid\n" + " name:\n" + " type: string\n" + " department:\n" + " type: string\n" + "required:\n" + " - id"; String yamlUser = "type: object\n" + "description: 'A User Object'\n" + "required:\n" + " - id\n" + "properties:\n" + " id:\n" + " type: string\n" + " format: uuid\n" + " name:\n" + " type: string\n"; String yamlEmployee = "type: object\n" + "description: An Employee Object\n" + "required:\n" + " - department\n" + "properties:\n" + " id:\n" + " type: string\n" + " format: email\n" + " department:\n" + " type: string"; final Map schemas = readAll(UberObject.class); assertEquals(schemas.size(), 3); SerializationMatchers.assertEqualsToYaml(schemas.get("UberObject"), yaml); SerializationMatchers.assertEqualsToYaml(schemas.get("UserObject"), yamlUser); SerializationMatchers.assertEqualsToYaml(schemas.get("EmployeeObject"), yamlEmployee); } @Schema(anyOf = {UserObject.class, EmployeeObject.class}) static class UberObject implements UserObject, EmployeeObject { private String id; private String name; private String department; @Override public String getDepartment() { return department; } @Override public String getId() { return id; } @Override public String getName() { return name; } } @Schema(description = "A User Object") interface UserObject { @Schema(format = "uuid", required = true) String getId(); String getName(); } @Schema(description = "An Employee Object", requiredProperties = {"department"}) interface EmployeeObject { @Schema(format = "email") String getId(); String getDepartment(); } @Test(description = "Shows how @Schema can be used to allow only certain data formats") public void testModelWithSpecificFormat() { String yaml = "AuthorizedUser:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " description: 'A valid user social security'\n" + " pattern: '^\\d{3}-?\\d{2}-?\\d{4}$'"; SerializationMatchers.assertEqualsToYaml(read(ClassWithIdConstraints.class), yaml); } @Schema(name = "AuthorizedUser") static class ClassWithIdConstraints { @Schema(pattern = "^\\d{3}-?\\d{2}-?\\d{4}$", description = "A valid user social security") private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } } @Test(description = "Shows how to restrict a particular schema") public void testExcludeSchema() { String yaml = "type: object\n" + "description: We don't store social security numbers here!\n" + "not:\n" + " $ref: \"#/components/schemas/AuthorizedUser\""; String yamlUser = "type: object\n" + "properties:\n" + " id:\n" + " type: string\n" + " description: 'A valid user social security'\n" + " pattern: '^\\d{3}-?\\d{2}-?\\d{4}$'"; Map map = readAll(ArbitraryDataReceiver.class); Yaml.prettyPrint(map); SerializationMatchers.assertEqualsToYaml(map.get("ArbitraryDataReceiver"), yaml); SerializationMatchers.assertEqualsToYaml(map.get("AuthorizedUser"), yamlUser); } @Schema(not = ClassWithIdConstraints.class, description = "We don't store social security numbers here!") static class ArbitraryDataReceiver { } @Test(description = "Shows how to override a definition with a schema reference") public void testSchemaReference() { String yaml = "NotAPet:\n" + " $ref: http://petstore.swagger.io/v2/swagger.json#/definitions/Tag"; SerializationMatchers.assertEqualsToYaml(read(NotAPet.class), yaml); } @Schema(ref = "http://petstore.swagger.io/v2/swagger.json#/definitions/Tag") static class NotAPet { } @Test(description = "Shows how to add a reference on a property") public void testPropertySchemaReference() { String yaml = "ModelWithSchemaPropertyReference:\n" + " type: object\n" + " properties:\n" + " notATag:\n" + " $ref: 'http://petstore.swagger.io/v2/swagger.json#/definitions/Tag'"; SerializationMatchers.assertEqualsToYaml(read(ModelWithSchemaPropertyReference.class), yaml); } static class ModelWithSchemaPropertyReference { @Schema(ref = "http://petstore.swagger.io/v2/swagger.json#/definitions/Tag") private String notATag; public String getNotATag() { return notATag; } public void setNotATag(String notATag) { this.notATag = notATag; } } @Test(description = "Shows how to override a property name") public void testPropertyNameOverride() { String yaml = "ModelWithPropertyNameOverride:\n" + " type: object\n" + " properties:\n" + " username:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(read(ModelWithPropertyNameOverride.class), yaml); } static class ModelWithPropertyNameOverride { public String getDefinitelyNotCalledUsername() { return definitelyNotCalledUsername; } public void setDefinitelyNotCalledUsername(String definitelyNotCalledUsername) { this.definitelyNotCalledUsername = definitelyNotCalledUsername; } @Schema(name = "username") private String definitelyNotCalledUsername; } @Test(description = "Shows how to override a model name") public void testModelNameOverride() { String yaml = "Employee:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(read(ModelWithNameOverride.class), yaml); } @Schema(name = "Employee") static class ModelWithNameOverride { private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } } @Test(description = "Shows how to provide model examples") public void testModelPropertyExampleOverride() { String yaml = "modelWithPropertyExampleOverride:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " example: abc-123"; SerializationMatchers.assertEqualsToYaml(read(modelWithPropertyExampleOverride.class), yaml); } static class modelWithPropertyExampleOverride { @Schema(example = "abc-123") private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } } @Test(description = "Shows how to provide model examples as json") public void testModelPropertyExampleJson() { String yaml = "ExampleJson:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " minimum: 2\n" + " example:\n" + " id: 19877734\n" + "modelWithPropertyExampleOverrideJson:\n" + " minimum: 2\n" + " type: object\n" + " properties:\n" + " exampleJson:\n" + " $ref: \"#/components/schemas/ExampleJson\"\n" + " example:\n" + " id: 19877734"; SerializationMatchers.assertEqualsToYaml(readAll(modelWithPropertyExampleOverrideJson.class), yaml); } @Schema(example = "{\"id\": 19877734}", minimum = "2") static class modelWithPropertyExampleOverrideJson { @Schema(example = "{\"id\": 19877734}", minimum = "2") private ExampleJson exampleJson; public ExampleJson getExampleJson() { return exampleJson; } public void setExampleJson(ExampleJson exampleJson) { this.exampleJson = exampleJson; } } @Test(description = "Shows how to provide model examples as json") public void testModelPropertyImplExampleJson() { String yaml = "ExampleJson:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " example:\n" + " id: 19877734\n" + "modelWithPropertyImplExampleOverrideJson:\n" + " type: object\n" + " properties:\n" + " exampleJson:\n" + " $ref: \"#/components/schemas/ExampleJson\"\n"; SerializationMatchers.assertEqualsToYaml(readAll(modelWithPropertyImplExampleOverrideJson.class), yaml); } static class modelWithPropertyImplExampleOverrideJson { @Schema(implementation = ExampleJson.class, example = "{\"id\": 19877734}") private String exampleJson; public String getExampleJson() { return exampleJson; } public void setExampleJson(String exampleJson) { this.exampleJson = exampleJson; } } /** * Test schema with json object defaultValue and example. */ @Test(description = "Shows how to provide model examples as json") public void testModelPropertyExampleDefaultJson() { String json = "{\"ExampleJsonExtended\": {" + "\"type\":\"object\"," + "\"properties\":{" + "\"id\":{" + "\"type\":\"integer\"," + "\"format\":\"int32\"" + "}," + "\"idType\":{" + "\"type\":\"string\"" + "}," + "\"isActive\":{" + "\"type\":\"boolean\"" + "}" + "}," + "\"example\":{" + "\"id\":19877734," + "\"idType\":\"employee code\"," + "\"isActive\":false" + "}," + "\"default\":{" + "\"id\":19877734," + "\"idType\":\"employee code\"," + "\"isActive\":false" + "}" + "}," + "\"modelWithPropertyExampleDefaultJson\":{" + "\"type\":\"object\"," + "\"properties\":{" + "\"exampleJsonExtended\":{" + "\"$ref\":\"#/components/schemas/ExampleJsonExtended\"" + "}" + "}" + "}" + "}"; SerializationMatchers.assertEqualsToJson(readAll(modelWithPropertyExampleDefaultJson.class), json); } static class modelWithPropertyExampleDefaultJson { final String SAMPLE = "{\"id\": 19877734, \"idType\":\"employee code\", \"isActive\":false}"; ExampleJsonExtended tester = new ExampleJsonExtended(); @Schema( example = SAMPLE, defaultValue = SAMPLE) private ExampleJsonExtended exampleJsonExtended; public ExampleJsonExtended getExampleJsonExtended() { return exampleJsonExtended; } public void setExampleJsonExtended(ExampleJsonExtended exampleJsonExtended) { this.exampleJsonExtended = exampleJsonExtended; } } @Test(description = "Shows how to provide model examples as json") public void testModelPropertyStringExampleJson() { String yaml = "modelWithPropertyStringExampleOverrideJson:\n" + " type: object\n" + " properties:\n" + " id:\n" + " minimum: 2\n" + " type: string\n" + " description: testdesc\n" + " example: '{\"id\":19877734}'"; SerializationMatchers.assertEqualsToYaml(readAll(modelWithPropertyStringExampleOverrideJson.class), yaml); } static class modelWithPropertyStringExampleOverrideJson { @Schema(type = "string", name = "id", example = "{\"id\": 19877734}", minimum = "2", description = "testdesc") private String exampleJson; public String getExampleJson() { return exampleJson; } public void setExampleJson(String exampleJson) { this.exampleJson = exampleJson; } } static class ExampleJson { private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } } static class ExampleJsonExtended { private int id; private String idType; private boolean isActive; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getIdType() { return idType; } public void setIdType(String idType) { this.idType = idType; } public boolean getIsActive() { return isActive; } public void setIsActive(boolean isActive) { this.isActive = isActive; } } @Test(description = "Shows how to provide an example array") public void testExampleArray() { String yaml = "modelExampleArray:\n" + " type: object\n" + " properties:\n" + " ids:\n" + " type: array\n" + " example:\n" + " - abc-123\n" + " - zz-aa-bb\n" + " items:\n" + " type: string"; Map schemaMap = readAll(modelExampleArray.class); SerializationMatchers.assertEqualsToYaml(schemaMap, yaml); } static class modelExampleArray { @ArraySchema(arraySchema = @Schema(example = "[\"abc-123\", \"zz-aa-bb\"]")) private String[] ids; public String[] getIds() { return ids; } public void setIds(String[] ids) { this.ids = ids; } } @Test(description = "Shows how to provide an array with specific format") public void testArrayWithPattern() { String yaml = "modelArrayWithPattern:\n" + " type: object\n" + " properties:\n" + " ids:\n" + " type: array\n" + " items:\n" + " pattern: \"[a-zA-Z]*\"\n" + " type: string"; Map schemaMap = readAll(modelArrayWithPattern.class); SerializationMatchers.assertEqualsToYaml(schemaMap, yaml); } static class modelArrayWithPattern { @Pattern(regexp="[a-zA-Z]*") private String[] ids; public String[] getIds() { return ids; } public void setIds(String[] ids) { this.ids = ids; } } @Test(description = "Show how to completely override an object example") public void testModelExampleOverride() { String yaml = "modelWithExampleOverride:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " example:\n" + " foo: bar\n" + " baz: true"; SerializationMatchers.assertEqualsToYaml(readAll(modelWithExampleOverride.class), yaml); } @Schema(example = "{\"foo\": \"bar\",\"baz\": true}") static class modelWithExampleOverride { private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } } @Test public void testModelWithBoolean() { String yaml = "ClassWithBoolean:\n" + " required:\n" + " - booleanObject\n" + " - booleanType\n" + " type: object\n" + " properties:\n" + " booleanObject:\n" + " type: boolean\n" + " description: my Boolean object field\n" + " booleanType:\n" + " type: boolean\n" + " description: my boolean type field\n"; SerializationMatchers.assertEqualsToYaml(read(ClassWithBoolean.class), yaml); } @Schema static class ClassWithBoolean { @Schema(required = true, description = "my Boolean object field") private Boolean booleanObject; @Schema(required = true, description = "my boolean type field") private boolean booleanType; public Boolean getBooleanObject() { return booleanObject; } public void setBooleanObject(Boolean booleanObject) { this.booleanObject = booleanObject; } public boolean getBooleanType() { return booleanType; } public void setBooleanType(boolean booleanType) { this.booleanType = booleanType; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/PolymorphicSubtypePropertyBleedTest.java ================================================ package io.swagger.v3.core.converting; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.models.media.ComposedSchema; import org.testng.annotations.Test; import javax.validation.constraints.NotNull; import java.lang.reflect.Field; import java.util.List; import java.util.Map; import static org.testng.Assert.*; import static org.testng.AssertJUnit.assertEquals; public class PolymorphicSubtypePropertyBleedTest { @Schema( description = "base", discriminatorProperty = "kind", oneOf = { ConcretionA.class } ) public static class BaseResponse { public String sharedField; public String kind; } @Schema(description = "subtype A") public static class ConcretionA extends BaseResponse { public String onlyInA; } public static class Wrapper { @NotNull public ConcretionA concretionA; } /** * Mimics how swagger-core resolves a bean property: * - schemaProperty=true * - propertyName set * - ctxAnnotations from the backing field (e.g. @NotNull) */ private io.swagger.v3.oas.models.media.Schema resolveAsBeanProperty( Class clazz, String propertyName, Field backingField, ModelConverterContextImpl ctx, ModelResolver resolver ) { AnnotatedType at = new AnnotatedType() .type(clazz) .schemaProperty(true) .propertyName(propertyName) .ctxAnnotations(backingField.getAnnotations()); return ctx.resolve(at); } /** * Mimics how resolveSubtypes(...) resolves a polymorphic subtype: * - NO schemaProperty(true) * - NO propertyName * - NO ctxAnnotations from some containing field */ private io.swagger.v3.oas.models.media.Schema resolveAsPolymorphicSubtype( Class clazz, ModelConverterContextImpl ctx, ModelResolver resolver ) { AnnotatedType at = new AnnotatedType() .type(clazz); return ctx.resolve(at); } /** * Baseline for comparison: new context, clean standalone schema resolution. */ private io.swagger.v3.oas.models.media.Schema resolveAsStandaloneSchema( Class clazz, ModelResolver resolver ) { ModelConverterContextImpl freshCtx = new ModelConverterContextImpl(resolver); AnnotatedType at = new AnnotatedType() .type(clazz); return freshCtx.resolve(at); } @Test public void subtypeResolution_shouldMatchStandalone_andNotBleedFromPropertyContext() throws Exception { ObjectMapper mapper = new ObjectMapper(); ModelResolver resolver = new ModelResolver(mapper); ModelConverterContextImpl sharedCtx = new ModelConverterContextImpl(resolver); // 1. Resolve ConcretionA in the bean property context Field wrapperField = Wrapper.class.getDeclaredField("concretionA"); io.swagger.v3.oas.models.media.Schema concretionAsPropertySchema = resolveAsBeanProperty( ConcretionA.class, "concretionA", wrapperField, sharedCtx, resolver ); assertNotNull(concretionAsPropertySchema, "bean property resolution returned null"); // 2. Resolve ConcretionA again, but this time as a polymorphic subtype using the SAME sharedCtx io.swagger.v3.oas.models.media.Schema concretionAsPolymorphicSchema = resolveAsPolymorphicSubtype( ConcretionA.class, sharedCtx, resolver ); assertNotNull(concretionAsPolymorphicSchema, "polymorphic subtype resolution returned null"); // 3. Resolve ConcretionA in a clean context to represent the canonical standalone subtype schema. io.swagger.v3.oas.models.media.Schema concretionStandaloneSchema = resolveAsStandaloneSchema( ConcretionA.class, resolver ); assertNotNull(concretionStandaloneSchema, "standalone subtype resolution returned null"); // nullable should be consistent between standalone and subtype assertEquals( concretionStandaloneSchema.getNullable(), concretionAsPolymorphicSchema.getNullable() ); // required list should match between standalone and subtype-in-sharedCtx List requiredStandalone = concretionStandaloneSchema.getRequired(); List requiredPolymorphic = concretionAsPolymorphicSchema.getRequired(); if (requiredStandalone == null) requiredStandalone = java.util.Collections.emptyList(); if (requiredPolymorphic == null) requiredPolymorphic = java.util.Collections.emptyList(); assertEquals( requiredStandalone, requiredPolymorphic ); // Name should match standalone. We don't want subtype schemas assertEquals( concretionStandaloneSchema.getName(), concretionAsPolymorphicSchema.getName() ); //Properties should still include subtype-specific fields like 'onlyInA'. Map propsStandalone = concretionStandaloneSchema.getProperties(); Map propsPolymorphic = concretionAsPolymorphicSchema.getProperties(); assertNotNull(propsPolymorphic); assertTrue(propsPolymorphic.containsKey("onlyInA")); assertEquals( propsStandalone == null ? java.util.Collections.emptySet() : propsStandalone.keySet(), propsPolymorphic.keySet() ); assertNotSame( concretionAsPropertySchema, concretionAsPolymorphicSchema ); } @Test public void polymorphicSubtype_mustContainSubtypeFragment_notJustBaseRef() { ObjectMapper mapper = new ObjectMapper(); ModelResolver resolver = new ModelResolver(mapper); ModelConverterContextImpl ctx = new ModelConverterContextImpl(resolver); AnnotatedType subtypeAT = new AnnotatedType() .type(ConcretionA.class) .schemaProperty(true); io.swagger.v3.oas.models.media.Schema resolvedSubtypeSchema = ctx.resolve(subtypeAT); assertTrue(resolvedSubtypeSchema.getProperties().containsKey("onlyInA")); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/SwaggerSerializerTest.java ================================================ package io.swagger.v3.core.converting; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.oas.models.Person; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.JsonAssert; import io.swagger.v3.core.util.OutputReplacer; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.QueryParameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.servers.Server; import org.testng.annotations.Test; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class SwaggerSerializerTest { @Test(description = "it should convert a spec") public void convertSpec() throws IOException { final Schema personModel = ModelConverters.getInstance().read(Person.class).get("Person"); final Schema errorModel = ModelConverters.getInstance().read(Error.class).get("Error"); final Info info = new Info() .version("1.0.0") .title("Swagger Petstore"); final Contact contact = new Contact() .name("Swagger API Team") .email("foo@bar.baz") .url("http://swagger.io"); info.setContact(contact); final Map map = new HashMap(); map.put("name", "value"); info.addExtension("x-test2", map); info.addExtension("x-test", "value"); final OpenAPI swagger = new OpenAPI() .info(info) .addServersItem(new Server() .url("http://petstore.swagger.io")) .schema("Person", personModel) .schema("Error", errorModel); final Operation get = new Operation() .summary("finds pets in the system") .description("a longer description") .addTagsItem("Pet Operations") .operationId("get pet by id") .deprecated(true); get.addParametersItem(new Parameter() .in("query") .name("tags") .description("tags to filter by") .required(false) .schema(new StringSchema()) ); get.addParametersItem(new Parameter() .in("path") .name("petId") .description("pet to fetch") .schema(new IntegerSchema().format("int64")) ); final ApiResponse response = new ApiResponse() .description("pets returned") .content(new Content() .addMediaType("application/json", new MediaType() .schema(new Schema().$ref("Person")) .example("fun"))); final ApiResponse errorResponse = new ApiResponse() .description("error response") .addLink("myLink", new Link() .description("a link") .operationId("theLinkedOperationId") .addParameter("userId", "gah") ) .content(new Content() .addMediaType("application/json", new MediaType() .schema(new Schema().$ref("Error")))); get.responses(new ApiResponses() .addApiResponse("200", response) .addApiResponse("default", errorResponse)); final Operation post = new Operation() .summary("adds a new pet") .description("you can add a new pet this way") .addTagsItem("Pet Operations") .operationId("add pet") .responses(new ApiResponses() .addApiResponse("default", errorResponse)) .requestBody(new RequestBody() .description("the pet to add") .content(new Content().addMediaType("*/*", new MediaType() .schema(new Schema().$ref("Person"))))); swagger.paths(new Paths().addPathItem("/pets", new PathItem() .get(get).post(post))); final String swaggerJson = Json.mapper().writeValueAsString(swagger); Json.prettyPrint(swagger); final OpenAPI rebuilt = Json.mapper().readValue(swaggerJson, OpenAPI.class); SerializationMatchers.assertEqualsToJson(rebuilt, swaggerJson); } @Test(description = "it should read the uber api") public void readUberApi() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "uber.json"); final OpenAPI swagger = Json.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(swagger); } @Test(description = "it should write a spec with parameter references") public void writeSpecWithParameterReferences() throws IOException { final Schema personModel = ModelConverters.getInstance().read(Person.class).get("Person"); final Info info = new Info() .version("1.0.0") .title("Swagger Petstore"); final Contact contact = new Contact() .name("Swagger API Team") .email("foo@bar.baz") .url("http://swagger.io"); info.setContact(contact); final OpenAPI swagger = new OpenAPI() .info(info) .addServersItem(new Server().url("http://petstore.swagger.io")) .schema("Person", personModel); final QueryParameter parameter = (QueryParameter) new QueryParameter() .name("id") .description("a common get parameter") .schema(new IntegerSchema()); final Operation get = new Operation() .summary("finds pets in the system") .description("a longer description") .operationId("get pet by id") .addParametersItem(new Parameter().$ref("#/parameters/Foo")); swagger .components(swagger.getComponents().addParameters("Foo", parameter)) .path("/pets", new PathItem().get(get)); final String swaggerJson = Json.mapper().writeValueAsString(swagger); final OpenAPI rebuilt = Json.mapper().readValue(swaggerJson, OpenAPI.class); JsonAssert.assertJsonEquals(Json.mapper(), Json.pretty(rebuilt), Json.pretty(swagger)); } @Test public void prettyPrintTest() throws IOException { final String json = ResourceUtils.loadClassResource(getClass(), "uber.json"); final OpenAPI swagger = Json.mapper().readValue(json, OpenAPI.class); final String outputStream = OutputReplacer.OUT.run(new OutputReplacer.Function() { @Override public void run() { Json.prettyPrint(swagger); } }); SerializationMatchers.assertEqualsToJson(swagger, outputStream); } @Test public void exceptionsTest() throws IOException { final String outputStream1 = OutputReplacer.ERROR.run(new OutputReplacer.Function() { @Override public void run() { Json.pretty(new ThrowHelper()); } }); assertTrue(outputStream1.contains(ThrowHelper.MESSAGE)); final String outputStream2 = OutputReplacer.ERROR.run(new OutputReplacer.Function() { @Override public void run() { Json.prettyPrint(new ThrowHelper()); } }); assertTrue(outputStream2.contains(ThrowHelper.MESSAGE)); } static class ThrowHelper { public static final String MESSAGE = "Test exception"; public String getValue() throws IOException { throw new IOException(MESSAGE); } public void setValue(String value) { } } @Test public void testDynamicRefSerialization() throws IOException { Schema dynamicRefSchema = new Schema<>(); dynamicRefSchema.set$dynamicRef("#node"); Components components = new Components().addSchemas("DynamicRefSchema", dynamicRefSchema); OpenAPI openAPI = new OpenAPI().components(components); String json = Json.mapper().writeValueAsString(openAPI); assertTrue(json.contains("\"$dynamicRef\":\"#node\"")); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/CustomAnnotationConverter.java ================================================ package io.swagger.v3.core.converting.override; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.resolving.resources.BidimensionalArray; import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.oas.models.media.Schema; import java.util.Iterator; public class CustomAnnotationConverter extends ModelResolver { public CustomAnnotationConverter(ObjectMapper mapper) { super(mapper); } @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { Schema s = chain.next().resolve(type, context, chain); if (s != null) { if ("array".equals(s.getType()) && s.getItems() != null && "array".equals(s.getItems().getType())) { BidimensionalArray.MySizeAnnotation size = AnnotationsUtils.getAnnotation(BidimensionalArray.MySizeAnnotation.class, type.getCtxAnnotations()); if (size != null) { s.getItems().maxItems(size.maxItems()); } } return s; } return null; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/CustomConverterTest.java ================================================ package io.swagger.v3.core.converting.override; import com.fasterxml.jackson.databind.JavaType; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Iterator; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; public class CustomConverterTest { @Test(description = "it should ignore properties with type Bar") public void testCustomConverter() { // add the custom converter final ModelConverters converters = new ModelConverters(); converters.addConverter(new CustomConverter()); final Schema model = converters.read(Foo.class).get("Foo"); assertNotNull(model); assertEquals(model.getProperties().size(), 1); final Schema barProperty = (Schema) model.getProperties().get("bar"); assertNull(barProperty); final Schema titleProperty = (Schema) model.getProperties().get("title"); assertNotNull(titleProperty); } class CustomConverter implements ModelConverter { @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { final JavaType jType = Json.mapper().constructType(type.getType()); if (jType != null) { final Class cls = jType.getRawClass(); if (cls.equals(Bar.class)) { return null; } else { return chain.next().resolve(type, context, chain); } } else { return null; } } } class Foo { public Bar bar = null; public String title = null; } class Bar { public String foo = null; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/CustomResolverTest.java ================================================ package io.swagger.v3.core.converting.override; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.jackson.TypeNameResolver; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import org.testng.annotations.Test; import java.util.*; import static org.testng.Assert.*; public class CustomResolverTest { @Test(description = "it should ignore properties with type Bar") public void testCustomConverter() { // add the custom converter final ModelConverters converters = new ModelConverters(); converters.addConverter(new CustomConverter(Json.mapper())); Map models = converters.readAll(Foo.class); Schema model = models.get("io.swagger.v3.core.converting.override.CustomResolverTest$Foo"); assertNotNull(model); assertEquals(model.getProperties().size(), 2); final Schema barProperty = (Schema) model.getProperties().get("bar"); assertEquals(barProperty.get$ref(), "#/components/schemas/io.swagger.v3.core.converting.override.CustomResolverTest$Bar"); final Schema titleProperty = (Schema)model.getProperties().get("title"); assertNotNull(titleProperty); model = models.get("io.swagger.v3.core.converting.override.CustomResolverTest$Bar"); assertNotNull(model); } @Test(description = "it should set the required mode based upon the field type") public void testCustomRequiredModeBasedUponTypeConverter() { // add the custom converter final ModelConverters converters = new ModelConverters(); converters.addConverter(new RequiredModeBasedUponFieldTypeResolver(Json.mapper())); Map models = converters.readAll(SuperFoo.class); Schema model = models.get("SuperFoo"); assertNotNull(model); assertEquals(model.getProperties().size(), 4); assertEquals(model.getRequired(), Collections.singletonList("bar")); final Schema fooProperty = (Schema) model.getProperties().get("foo"); assertEquals(fooProperty.get$ref(), "#/components/schemas/Foo"); Schema fooModel = models.get("Foo"); assertEquals(fooModel.getRequired(), Collections.singletonList("bar")); final Schema optionalBarProperty = (Schema) model.getProperties().get("optionalBar"); assertEquals(optionalBarProperty.get$ref(), "#/components/schemas/Bar"); Schema barModel = models.get("Bar"); assertNull(barModel.getRequired()); final Schema barProperty = (Schema) model.getProperties().get("bar"); assertEquals(barProperty.get$ref(), "#/components/schemas/Bar"); assertNull(barModel.getRequired()); final Schema titleProperty = (Schema) model.getProperties().get("string"); assertNotNull(titleProperty); } class CustomConverter extends ModelResolver { public CustomConverter(ObjectMapper mapper) { super(mapper, new QualifiedTypeNameResolver()); } } class QualifiedTypeNameResolver extends TypeNameResolver { @Override protected String nameForClass(Class cls, Set options) { String className = cls.getName().startsWith("java.") ? cls.getSimpleName() : cls.getName(); if (options.contains(Options.SKIP_API_MODEL)) { return className; } final io.swagger.v3.oas.annotations.media.Schema model = cls.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); final String modelName = model == null ? null : StringUtils.trimToNull(model.name()); return modelName == null ? className : modelName; } } class RequiredModeBasedUponFieldTypeResolver extends ModelResolver { public RequiredModeBasedUponFieldTypeResolver(ObjectMapper mapper) { super(mapper); } @Override protected io.swagger.v3.oas.annotations.media.Schema.RequiredMode resolveRequiredMode( io.swagger.v3.oas.annotations.media.Schema schema, JavaType type) { if (type.getRawClass().equals(Bar.class)) { return io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; } return super.resolveRequiredMode(schema, type); } } class SuperFoo { public Foo foo; public Optional optionalBar; public Bar bar; public Optional string; } class Foo { public Bar bar = null; public String title = null; } class Bar { public String foo = null; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/GenericModelConverter.java ================================================ package io.swagger.v3.core.converting.override; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.converting.override.resources.GenericModel; import io.swagger.v3.core.jackson.AbstractModelConverter; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.Schema; import java.util.Iterator; import java.util.Map.Entry; public class GenericModelConverter extends AbstractModelConverter { protected GenericModelConverter() { super(Json.mapper()); } @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator next) { if (type.getType() instanceof Class) { Class cls = (Class) type.getType(); if (GenericModel.class.isAssignableFrom(cls)) { Schema impl = new Schema(); impl.title(cls.getSimpleName()); for (Entry> entry : GenericModel.getDeclaredProperties().entrySet()) { impl.addProperties(entry.getKey(), context.resolve(new AnnotatedType(entry.getValue()))); } context.defineModel(impl.getTitle(), impl); return impl; } } if (next.hasNext()) { return next.next().resolve(type, context, next); } else { return null; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/ModelPropertyOverrideTest.java ================================================ package io.swagger.v3.core.converting.override; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converting.override.resources.MyCustomClass; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.BidimensionalArray; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Map; public class ModelPropertyOverrideTest { @Test public void overrideTest() throws Exception { ModelConverters.getInstance().addConverter(new SamplePropertyConverter()); final Map model = ModelConverters.getInstance().read(MyPojo.class); final String expected = "{" + " \"MyPojo\" : {" + " \"type\" : \"object\"," + " \"properties\" : {" + " \"id\" : {" + " \"type\" : \"string\"" + " }," + " \"myCustomClass\" : {" + " \"type\" : \"string\"," + " \"format\" : \"date-time\"" + " }" + " }" + " }" + "}"; SerializationMatchers.assertEqualsToJson(model, expected); } @Test public void extendedOverrideTest() throws Exception { ModelConverters.getInstance().addConverter(new SamplePropertyExtendedConverter(Json.mapper())); final Map model = ModelConverters.getInstance().read(MyPojo.class); final String expected = "{" + " \"MyPojo\" : {" + " \"type\" : \"object\"," + " \"properties\" : {" + " \"id\" : {" + " \"type\" : \"string\"" + " }," + " \"myCustomClass\" : {" + " \"type\" : \"string\"," + " \"format\" : \"date-time\"," + " \"description\" : \"instead of modeling this class in the documentation, we will model a string\"" + " }" + " }" + " }" + "}"; SerializationMatchers.assertEqualsToJson(model, expected); } public static class MyPojo { public String getId() { return ""; } public void setId(String id) { } @io.swagger.v3.oas.annotations.media.Schema(required = false, description = "instead of modeling this class in the documentation, we will model a string") public MyCustomClass getMyCustomClass() { return null; } public void setMyCustomClass(MyCustomClass myCustomClass) { } } @Test public void customAnnotationTest() throws Exception { ModelConverters.getInstance().addConverter(new CustomAnnotationConverter(Json.mapper())); final Map model = ModelConverters.getInstance().read(BidimensionalArray.class); final String expected = "BidimensionalArray:\n" + " type: object\n" + " properties:\n" + " withCustomAnnotation:\n" + " maxItems: 3\n" + " type: array\n" + " items:\n" + " maxItems: 2\n" + " type: array\n" + " items:\n" + " type: string\n" + " withHelperClass:\n" + " maxItems: 3\n" + " type: array\n" + " items:\n" + " maxItems: 2\n" + " type: array\n" + " items:\n" + " type: string\n" + " sized:\n" + " maxItems: 2\n" + " minItems: 0\n" + " type: array\n" + " items:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(model, expected); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/OverrideTest.java ================================================ package io.swagger.v3.core.converting.override; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converting.override.resources.GenericModel; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class OverrideTest { private static final String NAME = "name"; private static final String COUNT = "count"; @Test public void test() { GenericModel.declareProperty(NAME, String.class); GenericModel.declareProperty(COUNT, int.class); // create new instead of use singleton final ModelConverters converters = new ModelConverters(); converters.addConverter(new GenericModelConverter()); final Map read = converters.read(GenericModel.class); assertTrue(read.containsKey(GenericModel.class.getSimpleName())); final Schema model = read.get(GenericModel.class.getSimpleName()); assertTrue(model.getProperties().containsKey(NAME)); assertEquals(((Schema) model.getProperties().get(NAME)).getType(), "string"); assertTrue(model.getProperties().containsKey(COUNT)); assertEquals(((Schema) model.getProperties().get(COUNT)).getType(), "integer"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/SamplePropertyConverter.java ================================================ package io.swagger.v3.core.converting.override; import com.fasterxml.jackson.databind.JavaType; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.converting.override.resources.MyCustomClass; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.Schema; import java.util.Iterator; /** * Sample converter implementation which turns "MyCustomClass" into a DateTime property */ public class SamplePropertyConverter implements ModelConverter { @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { if (type.isSchemaProperty()) { JavaType _type = Json.mapper().constructType(type.getType()); if (_type != null) { Class cls = _type.getRawClass(); if (MyCustomClass.class.isAssignableFrom(cls)) { return new DateTimeSchema(); } } } if (chain.hasNext()) { return chain.next().resolve(type, context, chain); } else { return null; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/SamplePropertyExtendedConverter.java ================================================ package io.swagger.v3.core.converting.override; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.converting.override.resources.MyCustomClass; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.Schema; import java.util.Iterator; /** * Sample converter implementation which turns "MyCustomClass" into a DateTime property */ public class SamplePropertyExtendedConverter extends ModelResolver { public SamplePropertyExtendedConverter(ObjectMapper mapper) { super(mapper); } @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { if (type.isSchemaProperty()) { JavaType _type = Json.mapper().constructType(type.getType()); if (_type != null) { Class cls = _type.getRawClass(); if (MyCustomClass.class.isAssignableFrom(cls)) { Schema schema = new DateTimeSchema(); super.resolveSchemaMembers(schema, type); return schema; } } } if (chain.hasNext()) { return chain.next().resolve(type, context, chain); } else { return null; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/SnakeCaseConverterTest.java ================================================ package io.swagger.v3.core.converting.override; import com.google.common.collect.Sets; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.testng.annotations.Test; import javax.xml.bind.annotation.XmlRootElement; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import static io.swagger.v3.core.util.RefUtils.constructRef; import static io.swagger.v3.core.util.RefUtils.extractSimpleName; public class SnakeCaseConverterTest { @Test(description = "it should change naming style") public void testConvert() { // add the custom converter final SnakeCaseConverter snakeCaseConverter = new SnakeCaseConverter(); final ModelConverters converters = new ModelConverters(); converters.addConverter(snakeCaseConverter); final Map models = converters.readAll(SnakeCaseModel.class); final String json = "{" + " \"bar\":{" + " \"type\":\"object\"," + " \"properties\":{" + " \"foo\":{" + " \"type\":\"string\"" + " }" + " }" + " }," + " \"snake_case_model\":{" + " \"type\":\"object\"," + " \"properties\":{" + " \"bar\":{" + " \"$ref\":\"#/components/schemas/bar\"" + " }," + " \"title\":{" + " \"type\":\"string\"" + " }" + " }," + " \"xml\":{" + " \"name\":\"snakeCaseModel\"" + " }" + " }" + "}"; // TODO test xml if/when added to annotations and resolver Json.prettyPrint(models); SerializationMatchers.assertEqualsToJson(models, json); } /** * simple converter to rename models and field names into snake_case */ class SnakeCaseConverter implements ModelConverter { final Set primitives = Sets.newHashSet("string", "integer", "number", "boolean", "long"); @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { if (chain.hasNext()) { final ModelConverter converter = chain.next(); final Schema model = converter.resolve(type, context, chain); if (model != null) { final Map properties = model.getProperties(); final Map updatedProperties = new LinkedHashMap(); if (properties != null) { for (String key : properties.keySet()) { String convertedKey = toSnakeCase(key); Schema prop = properties.get(key); if (prop.get$ref() != null) { Pair refName = extractSimpleName(prop.get$ref()); if (!StringUtils.isBlank(refName.getRight())) { // skip if didn't resolve simple name prop.set$ref(constructRef(toSnakeCase(refName.getLeft()), refName.getRight())); } } updatedProperties.put(convertedKey, prop); } model.getProperties().clear(); model.setProperties(updatedProperties); } if (model.getName() != null) { String prevName = model.getName(); model.setName(toSnakeCase(model.getName())); context.defineModel(model.getName(), model, type, prevName); } return model; } } return null; } private String toSnakeCase(String str) { if (StringUtils.isBlank(str)) { return str; } String o = str.replaceAll("[A-Z\\d]", "_" + "$0").toLowerCase(); if (o.startsWith("_")) { return o.substring(1); } else { return o; } } } @XmlRootElement(name = "snakeCaseModel") class SnakeCaseModel { public Bar bar = null; public String title = null; } class Bar { public String foo = null; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/resources/GenericModel.java ================================================ package io.swagger.v3.core.converting.override.resources; import java.util.Collections; import java.util.HashMap; import java.util.Map; public class GenericModel { private static final Map> additionalPropertyTypes = new HashMap>(); private Map additionalProperties; public static void declareProperty(String key, Class cls) { additionalPropertyTypes.put(key, cls); } public static Map> getDeclaredProperties() { return Collections.unmodifiableMap(additionalPropertyTypes); } public static void undeclareProperty(String key) { additionalPropertyTypes.remove(key); } public void setProperty(String key, Object value) { if (value == null || additionalPropertyTypes.get(key).isAssignableFrom(value.getClass())) { additionalProperties.put(key, value); } } public Object getProperty(String key) { return additionalProperties.get(key); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/converting/override/resources/MyCustomClass.java ================================================ package io.swagger.v3.core.converting.override.resources; public class MyCustomClass { // does nothing, really } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/ComprehensiveOAS31ValidationTest.java ================================================ package io.swagger.v3.core.deserialization; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.models.OpenAPI; import org.testng.annotations.Test; import java.io.File; import java.io.IOException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; /** * Test class to validate the comprehensive OpenAPI 3.1 files. */ public class ComprehensiveOAS31ValidationTest { /** * Test to validate the comprehensive OpenAPI 3.1 file. * This test ensures that the file can be properly deserialized by the swagger-core library * and that all references are correctly resolved. */ @Test public void testComprehensiveOAS31Validation() throws IOException { // Path to the comprehensive OpenAPI 3.1 file String filePath = "src/test/resources/comprehensiveOAS31/comprehensive-openapi.yaml"; // Verify the file exists File file = new File(filePath); assertTrue(file.exists(), "Comprehensive OpenAPI 3.1 file does not exist: " + filePath); // Deserialize the file OpenAPI openAPI = Yaml31.mapper().readValue(file, OpenAPI.class); // Verify the file was properly deserialized assertNotNull(openAPI, "Failed to deserialize the comprehensive OpenAPI 3.1 file"); // Verify basic structure assertNotNull(openAPI.getInfo(), "Info object is missing"); assertNotNull(openAPI.getPaths(), "Paths object is missing"); assertNotNull(openAPI.getComponents(), "Components object is missing"); // Verify components assertNotNull(openAPI.getComponents().getSchemas(), "Schemas object is missing"); assertNotNull(openAPI.getComponents().getPathItems(), "PathItems object is missing"); assertNotNull(openAPI.getComponents().getParameters(), "Parameters object is missing"); assertNotNull(openAPI.getComponents().getRequestBodies(), "RequestBodies object is missing"); assertNotNull(openAPI.getComponents().getResponses(), "Responses object is missing"); assertNotNull(openAPI.getComponents().getHeaders(), "Headers object is missing"); assertNotNull(openAPI.getComponents().getSecuritySchemes(), "SecuritySchemes object is missing"); assertNotNull(openAPI.getComponents().getExamples(), "Examples object is missing"); assertNotNull(openAPI.getComponents().getLinks(), "Links object is missing"); assertNotNull(openAPI.getComponents().getCallbacks(), "Callbacks object is missing"); // Verify webhooks assertNotNull(openAPI.getWebhooks(), "Webhooks object is missing"); // Verify schemas assertTrue(openAPI.getComponents().getSchemas().size() > 0, "No schemas found"); // Verify paths assertTrue(openAPI.getPaths().size() > 0, "No paths found"); // Verify webhooks assertTrue(openAPI.getWebhooks().size() > 0, "No webhooks found"); } /** * Test round-trip serialization and deserialization of the comprehensive OpenAPI 3.1 file using YAML. * This test ensures that the file can be properly serialized and deserialized without losing information. */ @Test public void testComprehensiveOAS31YamlRoundTrip() throws IOException { // Path to the comprehensive OpenAPI 3.1 file String filePath = "src/test/resources/comprehensiveOAS31/comprehensive-openapi.yaml"; // Verify the file exists File file = new File(filePath); assertTrue(file.exists(), "Comprehensive OpenAPI 3.1 file does not exist: " + filePath); // Deserialize the file OpenAPI originalOpenAPI = Yaml31.mapper().readValue(file, OpenAPI.class); // Serialize to YAML String yaml = Yaml31.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Yaml31.mapper().readValue(yaml, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI, "Failed to deserialize the serialized YAML"); assertEquals(deserializedOpenAPI.getOpenapi(), "3.1.0", "OpenAPI version mismatch"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), originalOpenAPI.getInfo().getTitle(), "Title mismatch"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), originalOpenAPI.getInfo().getVersion(), "Version mismatch"); // Verify components assertNotNull(deserializedOpenAPI.getComponents(), "Components object is missing"); assertNotNull(deserializedOpenAPI.getComponents().getSchemas(), "Schemas object is missing"); assertEquals(deserializedOpenAPI.getComponents().getSchemas().size(), originalOpenAPI.getComponents().getSchemas().size(), "Schemas size mismatch"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths(), "Paths object is missing"); assertEquals(deserializedOpenAPI.getPaths().size(), originalOpenAPI.getPaths().size(), "Paths size mismatch"); // Verify webhooks assertNotNull(deserializedOpenAPI.getWebhooks(), "Webhooks object is missing"); assertEquals(deserializedOpenAPI.getWebhooks().size(), originalOpenAPI.getWebhooks().size(), "Webhooks size mismatch"); // Serialize again String yamlAgain = Yaml31.pretty(deserializedOpenAPI); // Compare YAML strings (normalize whitespace) SerializationMatchers.assertEqualsToYaml31(originalOpenAPI, yamlAgain); } /** * Test round-trip serialization and deserialization of the comprehensive OpenAPI 3.1 file using JSON. * This test ensures that the file can be properly serialized and deserialized without losing information. */ @Test public void testComprehensiveOAS31JsonRoundTrip() throws IOException { // Path to the comprehensive OpenAPI 3.1 file String filePath = "src/test/resources/comprehensiveOAS31/comprehensive-openapi.yaml"; // Verify the file exists File file = new File(filePath); assertTrue(file.exists(), "Comprehensive OpenAPI 3.1 file does not exist: " + filePath); // Deserialize the file OpenAPI originalOpenAPI = Yaml31.mapper().readValue(file, OpenAPI.class); // Serialize to JSON String json = Json31.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI, "Failed to deserialize the serialized JSON"); assertEquals(deserializedOpenAPI.getOpenapi(), "3.1.0", "OpenAPI version mismatch"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), originalOpenAPI.getInfo().getTitle(), "Title mismatch"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), originalOpenAPI.getInfo().getVersion(), "Version mismatch"); // Verify components assertNotNull(deserializedOpenAPI.getComponents(), "Components object is missing"); assertNotNull(deserializedOpenAPI.getComponents().getSchemas(), "Schemas object is missing"); assertEquals(deserializedOpenAPI.getComponents().getSchemas().size(), originalOpenAPI.getComponents().getSchemas().size(), "Schemas size mismatch"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths(), "Paths object is missing"); assertEquals(deserializedOpenAPI.getPaths().size(), originalOpenAPI.getPaths().size(), "Paths size mismatch"); // Verify webhooks assertNotNull(deserializedOpenAPI.getWebhooks(), "Webhooks object is missing"); assertEquals(deserializedOpenAPI.getWebhooks().size(), originalOpenAPI.getWebhooks().size(), "Webhooks size mismatch"); // Serialize again String jsonAgain = Json31.pretty(deserializedOpenAPI); // Compare JSON strings SerializationMatchers.assertEqualsToJson31(originalOpenAPI, jsonAgain); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/JsonDeserializationTest.java ================================================ package io.swagger.v3.core.deserialization; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.core.util.TestUtils; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.Encoding; import io.swagger.v3.oas.models.media.EncodingProperty; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import org.apache.commons.io.FileUtils; import org.testng.annotations.Test; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class JsonDeserializationTest { private final ObjectMapper m = Json.mapper(); @Test(description = "it should deserialize the petstore") public void testPetstore() throws IOException { final String json = ResourceUtils.loadClassResource(getClass(), "specFiles/petstore-3.0.json"); final Object swagger = m.readValue(json, OpenAPI.class); assertTrue(swagger instanceof OpenAPI); } @Test(description = "it should deserialize the composition test") public void testCompositionTest() throws IOException { final String json = ResourceUtils.loadClassResource(getClass(), "specFiles/compositionTest-3.0.json"); final Object deserialized = m.readValue(json, OpenAPI.class); assertTrue(deserialized instanceof OpenAPI); OpenAPI openAPI = (OpenAPI) deserialized; Schema lizardSchema = openAPI.getComponents().getSchemas().get("Lizard"); assertTrue(lizardSchema instanceof ComposedSchema); assertEquals(((ComposedSchema) lizardSchema).getAllOf().size(), 2); Schema petSchema = openAPI.getComponents().getSchemas().get("Pet"); assertEquals(petSchema.getDiscriminator().getPropertyName(), "pet_type"); assertEquals(petSchema.getDiscriminator().getMapping().get("cachorro"), "#/components/schemas/Dog"); } @Test(description = "it should deserialize a simple ObjectProperty") public void testObjectProperty() throws IOException { final String json = "{\n" + " \"type\":\"object\",\n" + " \"title\":\"objectProperty\",\n" + " \"description\":\"top level object\",\n" + " \"properties\":{\n" + " \"property1\":{\n" + " \"type\":\"string\",\n" + " \"description\":\"First property\"\n" + " },\n" + " \"property2\":{\n" + " \"type\":\"string\",\n" + " \"description\":\"Second property\"\n" + " },\n" + " \"property3\":{\n" + " \"type\":\"string\",\n" + " \"description\":\"Third property\"\n" + " }\n" + " }\n" + "}"; final Schema result = m.readValue(json, Schema.class); assertEquals(3, result.getProperties().size()); assertEquals("objectProperty", result.getTitle()); } @Test(description = "it should deserialize nested ObjectProperty(s)") public void testNestedObjectProperty() throws IOException { final String json = "{\n" + " \"type\":\"object\",\n" + " \"description\":\"top level object\",\n" + " \"properties\":{\n" + " \"property1\":{\n" + " \"type\":\"string\",\n" + " \"description\":\"First property\"\n" + " },\n" + " \"property2\":{\n" + " \"type\":\"string\",\n" + " \"description\":\"Second property\"\n" + " },\n" + " \"property3\":{\n" + " \"type\":\"object\",\n" + " \"description\":\"Third property\",\n" + " \"properties\":{\n" + " \"property1\":{\n" + " \"type\":\"string\",\n" + " \"description\":\"First nested property\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; final Schema result = m.readValue(json, Schema.class); final Map firstLevelProperties = result.getProperties(); assertEquals(firstLevelProperties.size(), 3); final Schema property3 = firstLevelProperties.get("property3"); final Map secondLevelProperties = property3.getProperties(); assertEquals(secondLevelProperties.size(), 1); } @Test public void testDeserializePetStoreFile() throws Exception { TestUtils.deserializeJsonFileFromClasspath("specFiles/petstore.json", OpenAPI.class); } @Test public void testDeserializeCompositionTest() throws Exception { TestUtils.deserializeJsonFileFromClasspath("specFiles/compositionTest.json", OpenAPI.class); } @Test public void testDeserializeAPathRef() throws Exception { final OpenAPI oas = TestUtils.deserializeJsonFileFromClasspath("specFiles/pathRef.json", OpenAPI.class); final PathItem petPath = oas.getPaths().get("/pet"); assertNotNull(petPath.get$ref()); assertEquals(petPath.get$ref(), "http://my.company.com/paths/health.json"); assertTrue(oas.getPaths().get("/user") instanceof PathItem); } @Test public void testDeserializeAResponseRef() throws Exception { final OpenAPI oas = TestUtils.deserializeJsonFileFromClasspath("specFiles/responseRef.json", OpenAPI.class); final ApiResponses responseMap = oas.getPaths().get("/pet").getPut().getResponses(); // TODO: missing response ref assertIsRefResponse(responseMap.get("405"), "http://my.company.com/responses/errors.json#/method-not-allowed"); assertIsRefResponse(responseMap.get("404"), "http://my.company.com/responses/errors.json#/not-found"); assertTrue(responseMap.get("400") instanceof ApiResponse); } private void assertIsRefResponse(Object response, String expectedRef) { assertTrue(response instanceof ApiResponse); ApiResponse refResponse = (ApiResponse) response; assertEquals(refResponse.get$ref(), expectedRef); } @Test public void testDeserializeSecurity() throws Exception { final OpenAPI swagger = TestUtils.deserializeJsonFileFromClasspath("specFiles/securityDefinitions.json", OpenAPI.class); final List security = swagger.getSecurity(); assertNotNull(security); assertEquals(security.size(), 3); final Map securitySchemes = swagger.getComponents().getSecuritySchemes(); assertNotNull(securitySchemes); assertEquals(securitySchemes.size(), 4); { final SecurityScheme scheme = securitySchemes.get("petstore_auth"); assertNotNull(scheme); assertEquals(scheme.getType().toString(), "oauth2"); assertEquals(scheme.getFlows().getImplicit().getAuthorizationUrl(), "http://petstore.swagger.io/oauth/dialog"); assertEquals(scheme.getFlows().getImplicit().getScopes().get("write:pets"), "modify pets in your account"); assertEquals(scheme.getFlows().getImplicit().getScopes().get("read:pets"), "read your pets"); } { final SecurityScheme scheme = securitySchemes.get("api_key"); assertNotNull(scheme); assertEquals(scheme.getType().toString(), "apiKey"); assertEquals(scheme.getIn().toString(), "header"); assertEquals(scheme.getName(), "api_key"); } { final SecurityScheme scheme = securitySchemes.get("http"); assertNotNull(scheme); assertEquals(scheme.getType().toString(), "http"); assertEquals(scheme.getScheme(), "basic"); } { final SecurityScheme scheme = securitySchemes.get("open_id_connect"); assertNotNull(scheme); assertEquals(scheme.getType().toString(), "openIdConnect"); assertEquals(scheme.getOpenIdConnectUrl(), "http://petstore.swagger.io/openid"); } { final SecurityRequirement securityRequirement = security.get(0); final List scopes = securityRequirement.get("petstore_auth"); assertNotNull(scopes); assertEquals(scopes.size(), 2); assertTrue(scopes.contains("write:pets")); assertTrue(scopes.contains("read:pets")); } { final SecurityRequirement securityRequirement = security.get(1); final List scopes = securityRequirement.get("api_key"); assertNotNull(scopes); assertTrue(scopes.isEmpty()); } { final SecurityRequirement securityRequirement = security.get(2); final List scopes = securityRequirement.get("http"); assertNotNull(scopes); assertTrue(scopes.isEmpty()); } } @Test(description = "it should deserialize a Header with style") public void deserializeHeaderWithStyle() throws IOException { final String json = "{\"description\":\"aaaa\",\"style\":\"simple\"}"; final Header p = m.readValue(json, Header.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize an Encoding with style") public void deserializeEncodingWithStyle() throws IOException { final String json = "{\"style\":\"spaceDelimited\"}"; final Encoding p = m.readValue(json, Encoding.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize an EncodingProperty with style") public void deserializeEncodingPropertyWithStyle() throws IOException { final String json = "{\"style\":\"spaceDelimited\"}"; final EncodingProperty p = m.readValue(json, EncodingProperty.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should desserialize Long schema correctly") public void deserializeLongSchema() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/oas3_2.yaml"); final OpenAPI swagger = Yaml.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(swagger); Schema s = swagger.getPaths().get("/withIntegerEnum/{stage}").getGet().getParameters().get(0).getSchema(); assertEquals(s.getEnum().get(0), 2147483647); assertEquals(s.getEnum().get(1), 3147483647L); assertEquals(s.getEnum().get(2), 31474836475505055L); assertEquals(s.getEnum().get(3), -9223372036854775808L); } @Test public void deserializeDateExample() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/swos-126.yaml"); final OpenAPI swagger = Yaml.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(swagger); Map props = swagger.getComponents().getSchemas().get("MyModel").getProperties(); assertTrue(Yaml.pretty().writeValueAsString(props.get("date")).contains("example: 2019-08-05")); assertTrue(Yaml.pretty().writeValueAsString(props.get("dateTime")).contains("example: 2019-08-05T12:34:56Z")); } @Test(description = "Deserialize ref callback") public void testDeserializeRefCallback() throws Exception { String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /simplecallback:\n" + " get:\n" + " summary: Simple get operation\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " callbacks:\n" + " testCallback1:\n" + " $ref: \"#/components/callbacks/Callback\"\n" + " callbacks:\n" + " testCallback1:\n" + " $ref: \"#/components/callbacks/Callback\"\n" + "components:\n" + " callbacks:\n" + " Callback:\n" + " /post:\n" + " description: Post Path Item\n"; OpenAPI oas = Yaml.mapper().readValue(yaml, OpenAPI.class); assertEquals(oas.getPaths().get("/simplecallback").getGet().getCallbacks().get("testCallback1").get$ref(), "#/components/callbacks/Callback"); } @Test(description = "Deserialize null enum item") public void testNullEnumItem() throws Exception { String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " tags:\n" + " - MyTag\n" + " summary: Operation Summary\n" + " description: Operation Description\n" + " operationId: operationId\n" + " parameters:\n" + " - name: subscriptionId\n" + " in: query\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " UserStatus:\n" + " type: integer\n" + " description: some int values with null\n" + " format: int32\n" + " enum:\n" + " - 1\n" + " - 2\n" + " - null\n"; OpenAPI oas = Yaml.mapper().readValue(yaml, OpenAPI.class); assertEquals(oas.getComponents().getSchemas().get("UserStatus").getEnum(), Arrays.asList(1, 2, null)); yaml = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " tags:\n" + " - MyTag\n" + " summary: Operation Summary\n" + " description: Operation Description\n" + " operationId: operationId\n" + " parameters:\n" + " - name: subscriptionId\n" + " in: query\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " UserStatus:\n" + " type: string\n" + " description: some int values with null\n" + " enum:\n" + " - 1\n" + " - 2\n" + " - null\n"; oas = Yaml.mapper().readValue(yaml, OpenAPI.class); assertEquals(oas.getComponents().getSchemas().get("UserStatus").getEnum(), Arrays.asList("1", "2", null)); } @Test public void testNullExampleDeserialization() throws Exception { String yamlNull = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " description: Operation Description\n" + " operationId: operationId\n" + "components:\n" + " schemas:\n" + " UserStatus:\n" + " type: string\n" + " example: null\n"; String yamlMissing = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " description: Operation Description\n" + " operationId: operationId\n" + "components:\n" + " schemas:\n" + " UserStatus:\n" + " type: string\n"; OpenAPI oas = Yaml.mapper().readValue(yamlNull, OpenAPI.class); Yaml.prettyPrint(oas); assertNull(oas.getComponents().getSchemas().get("UserStatus").getExample()); assertTrue(oas.getComponents().getSchemas().get("UserStatus").getExampleSetFlag()); oas = Yaml.mapper().readValue(yamlMissing, OpenAPI.class); Yaml.prettyPrint(oas); assertNull(oas.getComponents().getSchemas().get("UserStatus").getExample()); assertFalse(oas.getComponents().getSchemas().get("UserStatus").getExampleSetFlag()); Yaml.prettyPrint(oas); } @Test public void testNullExampleAndValues() throws Exception { String yamlNull = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " description: Operation Description\n" + " operationId: operationId\n" + "components:\n" + " schemas:\n" + " UserStatus:\n" + " type: object\n" + " example: null\n"; String yamlMissing = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " description: Operation Description\n" + " operationId: operationId\n" + "components:\n" + " schemas:\n" + " UserStatus:\n" + " type: object\n"; String yamlNotNull = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " description: Operation Description\n" + " operationId: operationId\n" + "components:\n" + " schemas:\n" + " UserStatus:\n" + " type: object\n" + " example:\n" + " value: bar\n"; String yamlValueNull = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " description: Operation Description\n" + " operationId: operationId\n" + "components:\n" + " examples:\n" + " UserStatus:\n" + " summary: string\n" + " value: null\n"; String yamlValueMissing = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " description: Operation Description\n" + " operationId: operationId\n" + "components:\n" + " examples:\n" + " UserStatus:\n" + " summary: string\n"; String yamlValueNotNull = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " description: Operation Description\n" + " operationId: operationId\n" + "components:\n" + " examples:\n" + " UserStatus:\n" + " summary: string\n" + " value: bar\n"; OpenAPI oas = Yaml.mapper().readValue(yamlNull, OpenAPI.class); Yaml.prettyPrint(oas); assertNull(oas.getComponents().getSchemas().get("UserStatus").getExample()); assertTrue(oas.getComponents().getSchemas().get("UserStatus").getExampleSetFlag()); assertEquals(Yaml.pretty(oas), yamlNull); oas = Yaml.mapper().readValue(yamlMissing, OpenAPI.class); Yaml.prettyPrint(oas); assertNull(oas.getComponents().getSchemas().get("UserStatus").getExample()); assertFalse(oas.getComponents().getSchemas().get("UserStatus").getExampleSetFlag()); assertEquals(Yaml.pretty(oas), yamlMissing); oas = Yaml.mapper().readValue(yamlNotNull, OpenAPI.class); Yaml.prettyPrint(oas); assertNotNull(oas.getComponents().getSchemas().get("UserStatus").getExample()); assertTrue(oas.getComponents().getSchemas().get("UserStatus").getExampleSetFlag()); assertEquals(Yaml.pretty(oas), yamlNotNull); oas = Yaml.mapper().readValue(yamlValueNull, OpenAPI.class); Yaml.prettyPrint(oas); Example ex = oas.getComponents().getExamples().get("UserStatus"); assertNull(ex.getValue()); assertTrue(ex.getValueSetFlag()); assertEquals(Yaml.pretty(oas), yamlValueNull); oas = Yaml.mapper().readValue(yamlValueMissing, OpenAPI.class); Yaml.prettyPrint(oas); ex = oas.getComponents().getExamples().get("UserStatus"); assertNull(ex.getValue()); assertFalse(ex.getValueSetFlag()); assertEquals(Yaml.pretty(oas), yamlValueMissing); oas = Yaml.mapper().readValue(yamlValueNotNull, OpenAPI.class); Yaml.prettyPrint(oas); ex = oas.getComponents().getExamples().get("UserStatus"); assertNotNull(ex.getValue()); assertTrue(ex.getValueSetFlag()); assertEquals(Yaml.pretty(oas), yamlValueNotNull); } @Test public void testExampleDeserializationOnMediaType() throws Exception { String content = FileUtils.readFileToString(new File("src/test/resources/specFiles/media-type-null-example.yaml"), "UTF-8"); OpenAPI openAPI = Yaml.mapper().readValue(content, OpenAPI.class); assertNull(openAPI.getPaths().get("/pets/{petId}").getGet().getResponses().get("200").getContent().get("application/json").getExample()); assertTrue(openAPI.getPaths().get("/pets/{petId}").getGet().getResponses().get("200").getContent().get("application/json").getExampleSetFlag()); assertNull(openAPI.getPaths().get("/pet").getPost().getResponses().get("200").getContent().get("application/json").getExample()); assertFalse(openAPI.getPaths().get("/pet").getPost().getResponses().get("200").getContent().get("application/json").getExampleSetFlag()); assertNotNull(openAPI.getPaths().get("/pet").getPost().getRequestBody().getContent().get("application/json").getExample()); assertTrue(openAPI.getPaths().get("/pet").getPost().getRequestBody().getContent().get("application/json").getExampleSetFlag()); } @Test public void testDateSchemaSerialization() throws Exception { String content = FileUtils.readFileToString(new File("src/test/resources/dateSchema.yaml"), "UTF-8"); OpenAPI openAPI = Yaml.mapper().readValue(content, OpenAPI.class); Yaml.prettyPrint(openAPI); SerializationMatchers.assertEqualsToYaml(openAPI, "openapi: 3.0.3\n" + "info:\n" + " title: Simple Inventory API\n" + " version: 1.0.0\n" + "paths:\n" + " /inventory:\n" + " get:\n" + " operationId: searchInventory\n" + " parameters:\n" + " - name: test\n" + " in: header\n" + " schema:\n" + " type: string\n" + " format: date\n" + " enum:\n" + " - 2023-12-12\n" + " default: 2023-12-12\n" + " responses:\n" + " \"200\":\n" + " description: search results matching criteria\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/InventoryItem\"\n" + "components:\n" + " schemas:\n" + " InventoryItem:\n" + " type: object\n" + " properties:\n" + " releaseDate:\n" + " type: string\n" + " format: date-time\n" + " example: 2016-08-29T09:12:33.001Z"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/ObjectPropertyTest.java ================================================ package io.swagger.v3.core.deserialization; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.io.IOException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class ObjectPropertyTest { @Test(description = "convert a model with object properties") public void readModelWithObjectProperty() throws IOException { String json = "{" + " \"properties\":{" + " \"id\":{" + " \"type\":\"string\"" + " }," + " \"someObject\":{" + " \"type\":\"object\"," + " \"x-foo\": \"vendor x\"," + " \"properties\":{" + " \"innerId\":{" + " \"type\":\"string\"" + " }" + " }" + " }" + " }" + "}"; Schema model = Json.mapper().readValue(json, Schema.class); Schema p = (Schema) model.getProperties().get("someObject"); assertTrue(p instanceof ObjectSchema); ObjectSchema op = (ObjectSchema) p; Schema sp = op.getProperties().get("innerId"); assertTrue(sp instanceof StringSchema); assertTrue(op.getExtensions() != null); assertNotNull(op.getExtensions().get("x-foo")); assertEquals(op.getExtensions().get("x-foo"), "vendor x"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/OpenAPI3_1DeserializationTest.java ================================================ package io.swagger.v3.core.deserialization; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.JsonSchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.io.IOException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; public class OpenAPI3_1DeserializationTest { @Test public void deserializePetstore3_1() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/petstore-3.1.yaml"); final OpenAPI swagger = Yaml31.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(swagger); assertEquals(swagger.getInfo().getLicense().getIdentifier(), "test"); } @Test public void deserializePetstore3_1More() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/petstore-3.1_more.yaml"); final OpenAPI swagger = Yaml31.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(swagger); assertEquals(swagger.getInfo().getLicense().getIdentifier(), "test"); } @Test public void deserializePetstore3_0() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/petstore-3.0.yaml"); final OpenAPI swagger = Yaml.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(swagger); assertNull(swagger.getInfo().getLicense().getIdentifier()); } @Test public void deserializeChangelog3_1() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/changelog-3.1.yaml"); final OpenAPI swagger = Yaml31.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(swagger); assertEquals(swagger.getInfo().getLicense().getIdentifier(), "test"); Yaml31.prettyPrint(swagger); SerializationMatchers.assertEqualsToYaml31(swagger, jsonString); } @Test public void testDeserializationOnOAS31() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/petstore-3.1_sample.yaml"); OpenAPI openAPI = Yaml31.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(openAPI); assertEquals(openAPI.getInfo().getTitle(), "Swagger Petstore"); assertEquals(openAPI.getInfo().getVersion(), "1.0.0"); assertEquals(openAPI.getInfo().getSummary(), "petstore sample for OAS 3.1.0"); assertEquals(openAPI.getInfo().getLicense().getName(), "MIT"); assertEquals(openAPI.getInfo().getLicense().getIdentifier(), "test"); assertNotNull(openAPI.getWebhooks()); assertFalse(openAPI.getWebhooks().isEmpty()); assertNotNull(openAPI.getWebhooks().get("newPet")); assertNotNull(openAPI.getWebhooks().get("newPet").getPost()); assertNotNull(openAPI.getComponents().getPathItems()); assertNotNull(openAPI.getComponents().getPathItems().get("/pet")); assertEquals(openAPI.getComponents().getPathItems().get("/pet").getDescription(), "get a pet"); assertNotNull(openAPI.getComponents().getPathItems().get("/pet").getGet()); assertEquals(openAPI.getComponents().getPathItems().get("/pet").getGet().getOperationId(), "getPet"); assertNotNull(openAPI.getComponents().getSchemas()); assertNotNull(openAPI.getComponents().getSchemas().get("Pet")); assertNotNull(openAPI.getComponents().getSchemas().get("Pet").getDiscriminator()); assertNotNull(openAPI.getComponents().getSchemas().get("Pet").getDiscriminator().getExtensions()); assertEquals(openAPI.getComponents().getSchemas().get("Pet").getDiscriminator().getExtensions().get("x-test-extension"), "extended"); assertNotNull(openAPI.getComponents().getResponses()); assertNotNull(openAPI.getComponents().getResponses().get("201")); assertEquals(openAPI.getComponents().getResponses().get("201").getDescription(), "api response description"); assertNotNull(openAPI.getComponents().getParameters()); assertNotNull(openAPI.getComponents().getParameters().get("param")); assertEquals(openAPI.getComponents().getParameters().get("param").getIn(), "query"); assertEquals(openAPI.getComponents().getParameters().get("param").getName(), "param0"); assertEquals(openAPI.getComponents().getParameters().get("param").getDescription(), "parameter description"); assertNotNull(openAPI.getComponents().getExamples()); assertNotNull(openAPI.getComponents().getExamples().get("example")); assertEquals(openAPI.getComponents().getExamples().get("example").getDescription(), "example description"); assertEquals(openAPI.getComponents().getExamples().get("example").getSummary(), "example summary"); assertEquals(openAPI.getComponents().getExamples().get("example").getValue(), "This is an example"); assertNotNull(openAPI.getComponents().getRequestBodies()); assertNotNull(openAPI.getComponents().getRequestBodies().get("body")); assertNotNull(openAPI.getComponents().getHeaders()); assertNotNull(openAPI.getComponents().getHeaders().get("test-head")); assertEquals(openAPI.getComponents().getHeaders().get("test-head").getDescription(), "test header description"); assertNotNull(openAPI.getComponents().getSecuritySchemes()); assertNotNull(openAPI.getComponents().getSecuritySchemes().get("basic")); assertEquals(openAPI.getComponents().getSecuritySchemes().get("basic").getDescription(), "security description"); assertEquals(openAPI.getComponents().getSecuritySchemes().get("basic").getType().toString(), "http"); assertNotNull(openAPI.getComponents().getLinks()); assertNotNull(openAPI.getComponents().getLinks().get("Link")); assertEquals(openAPI.getComponents().getLinks().get("Link").getOperationRef(), "#/paths/~12.0~1repositories~1{username}/get"); assertNotNull(openAPI.getComponents().getCallbacks()); assertNotNull(openAPI.getComponents().getCallbacks().get("TestCallback")); openAPI = Yaml.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(openAPI); assertNull(openAPI.getInfo().getSummary()); assertNull(openAPI.getWebhooks()); assertNull(openAPI.getComponents().getPathItems()); assertNull(openAPI.getComponents().getSchemas().get("Pet").getDiscriminator().getExtensions()); } @Test public void testDeserializationOnOAS30() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/petstore-3.1_sample.yaml"); OpenAPI openAPI = Yaml.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(openAPI); assertEquals(openAPI.getInfo().getTitle(), "Swagger Petstore"); assertEquals(openAPI.getInfo().getVersion(), "1.0.0"); assertNull(openAPI.getInfo().getSummary()); assertEquals(openAPI.getInfo().getLicense().getName(), "MIT"); assertNull(openAPI.getInfo().getLicense().getIdentifier()); assertNull(openAPI.getWebhooks()); assertNull(openAPI.getComponents().getPathItems()); assertNotNull(openAPI.getComponents().getSchemas()); assertNotNull(openAPI.getComponents().getSchemas().get("Pet")); assertNotNull(openAPI.getComponents().getSchemas().get("Pet").getDiscriminator()); assertNull(openAPI.getComponents().getSchemas().get("Pet").getDiscriminator().getExtensions()); assertNotNull(openAPI.getComponents().getResponses()); assertNotNull(openAPI.getComponents().getResponses().get("201")); assertEquals(openAPI.getComponents().getResponses().get("201").getDescription(), "api response description"); assertNotNull(openAPI.getComponents().getParameters()); assertNotNull(openAPI.getComponents().getParameters().get("param")); assertEquals(openAPI.getComponents().getParameters().get("param").getIn(), "query"); assertEquals(openAPI.getComponents().getParameters().get("param").getName(), "param0"); assertEquals(openAPI.getComponents().getParameters().get("param").getDescription(), "parameter description"); assertNotNull(openAPI.getComponents().getExamples()); assertNotNull(openAPI.getComponents().getExamples().get("example")); assertEquals(openAPI.getComponents().getExamples().get("example").getDescription(), "example description"); assertEquals(openAPI.getComponents().getExamples().get("example").getSummary(), "example summary"); assertEquals(openAPI.getComponents().getExamples().get("example").getValue(), "This is an example"); assertNotNull(openAPI.getComponents().getRequestBodies()); assertNotNull(openAPI.getComponents().getRequestBodies().get("body")); assertNotNull(openAPI.getComponents().getHeaders()); assertNotNull(openAPI.getComponents().getHeaders().get("test-head")); assertEquals(openAPI.getComponents().getHeaders().get("test-head").getDescription(), "test header description"); assertNotNull(openAPI.getComponents().getSecuritySchemes()); assertNotNull(openAPI.getComponents().getSecuritySchemes().get("basic")); assertEquals(openAPI.getComponents().getSecuritySchemes().get("basic").getDescription(), "security description"); assertEquals(openAPI.getComponents().getSecuritySchemes().get("basic").getType().toString(), "http"); assertNotNull(openAPI.getComponents().getLinks()); assertNotNull(openAPI.getComponents().getLinks().get("Link")); assertEquals(openAPI.getComponents().getLinks().get("Link").getOperationRef(), "#/paths/~12.0~1repositories~1{username}/get"); assertNotNull(openAPI.getComponents().getCallbacks()); assertNotNull(openAPI.getComponents().getCallbacks().get("TestCallback")); openAPI = Yaml.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(openAPI); } @Test public void testRefDeserializationOnOAS31() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/petstore-3.1_refs_siblings.yaml"); OpenAPI openAPI = Yaml31.mapper().readValue(jsonString, OpenAPI.class); assertEquals(openAPI.getPaths().get("/ref_pet").get$ref(), "#/components/pathItems/pet"); assertEquals(openAPI.getPaths().get("/ref_pet").getDescription(), "ref pathItem description"); assertEquals(openAPI.getPaths().get("/ref_pet").getSummary(), "ref pathItem summary"); assertEquals(openAPI.getPaths().get("/pets").getPost().getParameters().get(0).get$ref(), "#/components/parameters/testParameter"); assertEquals(openAPI.getPaths().get("/pets").getPost().getParameters().get(0).getDescription(), "ref parameter description"); assertEquals(openAPI.getPaths().get("/pets").getPost().getParameters().get(1).getName(), "randomParam"); assertEquals(openAPI.getPaths().get("/pets").getPost().getParameters().get(1).getIn(), "query"); assertEquals(openAPI.getPaths().get("/pets").getPost().getParameters().get(1).getExamples().get("refExample").get$ref(), "#/components/examples/testExample"); assertEquals(openAPI.getPaths().get("/pets").getPost().getParameters().get(1).getExamples().get("refExample").getDescription(), "ref example description"); assertEquals(openAPI.getPaths().get("/pets").getPost().getParameters().get(1).getExamples().get("refExample").getSummary(), "ref example summary"); assertEquals(openAPI.getPaths().get("/pets").getPost().getCallbacks().get("callIt").get$ref(), "#/components/callbacks/TestCallback"); assertEquals(openAPI.getPaths().get("/pets").getPost().getRequestBody().get$ref(), "#/components/requestBodies/body"); assertEquals(openAPI.getPaths().get("/pets").getPost().getRequestBody().getDescription(), "ref request body description"); assertEquals(openAPI.getPaths().get("/pets").getPost().getResponses().get("201").get$ref(), "#/components/responses/okResponse"); assertEquals(openAPI.getPaths().get("/pets").getPost().getResponses().get("201").getDescription(), "ref response description"); assertEquals(openAPI.getPaths().get("/pets").getPost().getResponses().get("default").getHeaders().get("head").get$ref(), "#/components/headers/head"); assertEquals(openAPI.getPaths().get("/pets").getPost().getResponses().get("default").getHeaders().get("head").getDescription(), "ref header description"); } @Test public void testBooleanSchemaDeserialization() throws Exception{ OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .components(new Components().addSchemas("test", new Schema().booleanSchemaValue(true))); String json = Json31.pretty(openAPI); String yaml = Yaml31.pretty(openAPI); OpenAPI oas = Json31.mapper().readValue(json, OpenAPI.class); assertEquals(oas.getComponents().getSchemas().get("test").getBooleanSchemaValue(), Boolean.TRUE); Schema schema = Json31.mapper().readValue("true", Schema.class); assertEquals(schema.getBooleanSchemaValue(), Boolean.TRUE); oas = Yaml31.mapper().readValue(yaml, OpenAPI.class); assertEquals(oas.getComponents().getSchemas().get("test").getBooleanSchemaValue(), Boolean.TRUE); schema = Yaml31.mapper().readValue("true", Schema.class); assertEquals(schema.getBooleanSchemaValue(), Boolean.TRUE); json = Json.pretty(openAPI); yaml = Yaml.pretty(openAPI); oas = Json.mapper().readValue(json, OpenAPI.class); assertNull(oas.getComponents().getSchemas().get("test").getBooleanSchemaValue()); oas = Yaml.mapper().readValue(yaml, OpenAPI.class); assertNull(oas.getComponents().getSchemas().get("test").getBooleanSchemaValue()); } @Test public void testDynamicRefDeserializationOnOAS31() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/specWithDynamicRef.yaml"); OpenAPI openAPI = Yaml31.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(openAPI); Schema baseNodeSchema = openAPI.getComponents().getSchemas().get("BaseNode"); assertNotNull(baseNodeSchema); assertNotNull(baseNodeSchema.getProperties().get("children")); JsonSchema childrenSchema = (JsonSchema) baseNodeSchema.getProperties().get("children"); assertEquals(childrenSchema.getItems().get$dynamicRef(), "#node"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/ParameterDeSerializationTest.java ================================================ package io.swagger.v3.core.deserialization; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import org.testng.annotations.Test; import java.io.IOException; import java.util.Arrays; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class ParameterDeSerializationTest { private final ObjectMapper m = Json.mapper(); @Test(description = "it should deserialize a QueryParameter") public void deserializeQueryParameter() throws IOException { final String json = "{\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"string\"}}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize a QueryParameter with style") public void deserializeQueryParameterWithStyle() throws IOException { final String json = "{\"in\":\"query\",\"style\":\"form\",\"required\":false,\"schema\":{\"type\":\"string\"}}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize a QueryParameter with array") public void deserializeArrayQueryParameter() throws IOException { final String json = "{" + " \"in\":\"query\"," + " \"required\":false," + " \"schema\":{" + " \"type\":\"array\"," + " \"items\":{" + " \"type\":\"string\"" + " }" + " }" + "}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize a PathParameter") public void deserializePathParameter() throws IOException { final String json = "{\"in\":\"query\",\"required\":true,\"schema\":{\"type\":\"string\"}}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); assertTrue(p.getRequired()); } @Test(description = "it should deserialize a PathParameter with string array") public void deserializeStringArrayPathParameter() throws IOException { final String json = "{\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize a PathParameter with integer array ") public void deserializeIntegerArrayPathParameter() throws IOException { final String json = "{" + " \"in\":\"path\"," + " \"required\":true," + " \"schema\":{" + " \"type\":\"array\"," + " \"items\":{" + " \"type\":\"integer\"," + " \"format\":\"int32\"" + " }}" + "}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize a HeaderParameter") public void deserializeHeaderParameter() throws IOException { final String json = "{\"in\":\"header\",\"required\":true,\"schema\":{\"type\":\"string\"}}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize a string array HeaderParameter") public void deserializeStringArrayHeaderParameter() throws IOException { final String json = "{\"in\":\"header\",\"required\":true,\"schema\":{\"type\":\"string\"}}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize a BodyParameter") public void deserializeBodyParameter() throws IOException { final String json = "{\"content\":{" + " \"*/*\":{" + " \"schema\":{" + " \"type\":\"string\"}}}}"; final RequestBody p = m.readValue(json, RequestBody.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize a read only parameter") public void deserializeReadOnlyParameter() throws IOException { final String json = "{\"in\":\"path\"," + "\"content\":{" + " \"*/*\":{" + " \"schema\":{" + " \"type\":\"string\"," + " \"readOnly\":true}}}}"; final Parameter p = m.readValue(json, Parameter.class); assertTrue(p.getContent().get("*/*").getSchema().getReadOnly()); } @Test(description = "it should deserialize an array BodyParameter") public void deserializeArrayBodyParameter() throws IOException { final String json = "{\"content\":{\"*/*\":{\"schema\":{\"type\":\"array\",\"items\":{\"$ref\":\"#/definitions/Cat\"}}}}}"; final RequestBody p = m.readValue(json, RequestBody.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should deserialize a path parameter with enum") public void deserializeEnumPathParameter() throws IOException { final String json = "{" + " \"in\":\"path\"," + " \"required\":true," + " \"schema\":{" + " \"type\":\"array\"," + " \"items\":{" + " \"type\":\"string\"," + " \"enum\":[\"a\",\"b\",\"c\"]" + " }" + "}}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); ArraySchema as = (ArraySchema) p.getSchema(); assertEquals(((StringSchema) as.getItems()).getEnum(), Arrays.asList("a", "b", "c")); } @Test(description = "it should deserialize a number path parameter with enum") public void deserializeNumberEnumPathParameter() throws IOException { final String json = "{" + " \"in\":\"path\"," + " \"required\":true," + " \"schema\":{" + " \"type\":\"array\"," + " \"items\":{" + " \"type\":\"integer\"," + " \"format\":\"int32\"," + " \"enum\":[1,2,3]" + " }" + " }" + "}"; final Parameter p = m.readValue(json, Parameter.class); SerializationMatchers.assertEqualsToJson(p, json); assertEquals(((IntegerSchema) ((ArraySchema) p.getSchema()).getItems()).getEnum(), Arrays.asList(1, 2, 3)); } @Test(description = "should serialize correctly typed numeric enums") public void testIssue1765() throws Exception { String yaml = "openapi: '3.0.1'\n" + "paths:\n" + " /test:\n" + " get:\n" + " parameters:\n" + " - name: \"days\"\n" + " in: \"path\"\n" + " required: true\n" + " schema:\n" + " type: \"integer\"\n" + " format: \"int32\"\n" + " enum:\n" + " - 1\n" + " - 2\n" + " - 3\n" + " - 4\n" + " - 5\n" + " responses:\n" + " default:\n" + " description: great"; OpenAPI swagger = Yaml.mapper().readValue(yaml, OpenAPI.class); SerializationMatchers.assertEqualsToYaml(swagger, yaml); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/SchemaDeserializationTest.java ================================================ package io.swagger.v3.core.deserialization; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.models.OpenAPI; import org.testng.annotations.Test; import java.io.IOException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class SchemaDeserializationTest { @Test public void deserializeRefSchema3_1() throws IOException { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/petstore-3.1_refs_siblings.yaml"); final OpenAPI openAPI = Yaml31.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(openAPI); assertNotNull(openAPI.getComponents()); assertNotNull(openAPI.getComponents().getSchemas()); assertNotNull(openAPI.getComponents().getSchemas().get("AnotherPet")); assertEquals(openAPI.getComponents().getSchemas().get("AnotherPet").get$ref(), "#/components/schemas/Pet"); assertEquals(openAPI.getComponents().getSchemas().get("AnotherPet").getTitle(), "Another Pet"); assertEquals(openAPI.getComponents().getSchemas().get("AnotherPet").getDescription(), "Another Pet for petstore referencing Pet schema"); assertNotNull(openAPI.getComponents().getSchemas().get("AnotherPet").getProperties()); assertNotNull(openAPI.getComponents().getSchemas().get("AnotherPet").getProperties().get("category")); assertNotNull(openAPI.getComponents().getSchemas().get("AnotherPet").getProperties().get("photoUrl")); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/properties/ArrayPropertyDeserializerTest.java ================================================ package io.swagger.v3.core.deserialization.properties; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.responses.ApiResponse; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class ArrayPropertyDeserializerTest { private static final String yaml = " operationId: something\n" + " responses:\n" + " \"200\":\n" + " content:\n" + " '*/*':\n" + " examples:\n" + " simple:\n" + " value: Array example\n" + " more:\n" + " value: with two items\n" + " description: OK\n" + " schema:\n" + " type: array\n" + " minItems: 3\n" + " maxItems: 100\n" + " items:\n" + " type: string\n"; @Test(description = "it should includes the example in the arrayproperty") public void testArrayDeserialization() throws Exception { Operation operation = Yaml.mapper().readValue(yaml, Operation.class); ApiResponse response = operation.getResponses().get("200"); assertNotNull(response); MediaType media = response.getContent().get("*/*"); Schema responseSchema = media.getSchema(); assertTrue(media.getExamples().size() == 2); assertNotNull(responseSchema); assertTrue(responseSchema instanceof ArraySchema); ArraySchema mp = (ArraySchema) responseSchema; assertEquals(mp.getMinItems(), new Integer(3)); assertEquals(mp.getMaxItems(), new Integer(100)); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/properties/JsonPropertiesDeserializationTest.java ================================================ package io.swagger.v3.core.deserialization.properties; import io.swagger.v3.core.util.TestUtils; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.MapSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.util.List; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class JsonPropertiesDeserializationTest { @Test(description = "should deserialize a string property with constraints") public void testDeserializeConstrainedStringProperty() throws Exception { OpenAPI oas = TestUtils.deserializeJsonFileFromClasspath("specFiles/propertiesWithConstraints.json", OpenAPI.class); StringSchema property = (StringSchema) oas.getComponents().getSchemas().get("Health").getProperties().get("string_with_constraints"); assertEquals(property.getMinLength(), Integer.valueOf(10)); assertEquals(property.getMaxLength(), Integer.valueOf(100)); assertEquals(property.getPattern(), "apattern"); } @Test(description = "should deserialize an array property with constraints") public void testDeserializeConstrainedArrayProperties() throws Exception { OpenAPI oas = TestUtils.deserializeJsonFileFromClasspath("specFiles/propertiesWithConstraints.json", OpenAPI.class); Map properties = oas.getComponents().getSchemas().get("Health").getProperties(); ArraySchema withMin = (ArraySchema) properties.get("array_with_min"); assertEquals(withMin.getMinItems(), Integer.valueOf(5)); assertNull(withMin.getMaxItems()); assertNull(withMin.getUniqueItems()); ArraySchema withMax = (ArraySchema) properties.get("array_with_max"); assertNull(withMax.getMinItems()); assertEquals(withMax.getMaxItems(), Integer.valueOf(10)); assertNull(withMax.getUniqueItems()); ArraySchema withUnique = (ArraySchema) properties.get("array_with_unique"); assertNull(withUnique.getMinItems()); assertNull(withUnique.getMaxItems()); assertEquals(withUnique.getUniqueItems(), Boolean.TRUE); ArraySchema withAll = (ArraySchema) properties.get("array_with_all"); assertEquals(withAll.getMinItems(), Integer.valueOf(1)); assertEquals(withAll.getMaxItems(), Integer.valueOf(10)); assertEquals(withAll.getUniqueItems(), Boolean.TRUE); } @Test(description = "should deserialize a property with vendor extensions of different types") public void testDeserializePropertyWithVendorExtensions() throws Exception { OpenAPI oas = TestUtils.deserializeJsonFileFromClasspath("specFiles/propertyWithVendorExtensions.json", OpenAPI.class); Map oasVendorExtensions = oas.getExtensions(); Map vendorExtensions = ((Schema) oas.getComponents().getSchemas().get("Health").getProperties().get("status")).getExtensions(); assertVendorExtensions(oasVendorExtensions); assertVendorExtensions(vendorExtensions); //check for vendor extensions in array property types vendorExtensions = ((Schema) oas.getComponents().getSchemas().get("Health").getProperties().get("array")).getExtensions(); String xStringValue = (String) vendorExtensions.get("x-string-value"); assertNotNull(xStringValue); assertEquals(xStringValue, "string_value"); } private void assertVendorExtensions(Map vendorExtensions) { assertNotNull(vendorExtensions); assertEquals(6, vendorExtensions.size()); String xStringValue = (String) vendorExtensions.get("x-string-value"); assertNotNull(xStringValue); assertEquals(xStringValue, "Hello World"); assertTrue(vendorExtensions.containsKey("x-null-value")); assertNull(vendorExtensions.get("x-null-value")); Map xMapValue = (Map) vendorExtensions.get("x-map-value"); assertNotNull(xMapValue); assertEquals(xMapValue.get("hello"), "world"); assertEquals(xMapValue.get("foo"), "bar"); List xListValue = (List) vendorExtensions.get("x-list-value"); assertNotNull(xListValue); assertEquals(xListValue.get(0), "Hello"); assertEquals(xListValue.get(1), "World"); Integer xNumberValue = (Integer) vendorExtensions.get("x-number-value"); assertNotNull(xNumberValue); assertEquals(xNumberValue.intValue(), 123); Boolean xBooleanValue = (Boolean) vendorExtensions.get("x-boolean-value"); assertNotNull(xBooleanValue); assertTrue(xBooleanValue); assertFalse(vendorExtensions.containsKey("not-an-extension")); } @Test public void shouldDeserializeArrayPropertyMinItems() throws Exception { String path = "json-schema-validation/array.json"; ArraySchema property = (ArraySchema) TestUtils.deserializeJsonFileFromClasspath(path, Schema.class); assertNotNull(property.getMinItems()); assertEquals(property.getMinItems().intValue(), 1); } @Test public void shouldDeserializeArrayPropertyMaxItems() throws Exception { String path = "json-schema-validation/array.json"; ArraySchema property = (ArraySchema) TestUtils.deserializeJsonFileFromClasspath(path, Schema.class); assertNotNull(property.getMaxItems()); assertEquals(property.getMaxItems().intValue(), 10); } @Test public void shouldDeserializeArrayPropertyUniqueItems() throws Exception { String path = "json-schema-validation/array.json"; ArraySchema property = (ArraySchema) TestUtils.deserializeJsonFileFromClasspath(path, Schema.class); assertNotNull(property.getUniqueItems()); assertTrue(property.getUniqueItems()); } @Test public void givenMapProperty_shouldDeserializeMinProperties() { String path = "json-schema-validation/map.json"; MapSchema property = (MapSchema) TestUtils.deserializeJsonFileFromClasspath(path, Schema.class); assertNotNull(property.getMinProperties()); assertEquals(property.getMinProperties().intValue(), 1); } @Test public void givenMapProperty_shouldDeserializeMaxProperties() { String path = "json-schema-validation/map.json"; MapSchema property = (MapSchema) TestUtils.deserializeJsonFileFromClasspath(path, Schema.class); assertNotNull(property.getMaxProperties()); assertEquals(property.getMaxProperties().intValue(), 10); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/properties/MapPropertyDeserializerTest.java ================================================ package io.swagger.v3.core.deserialization.properties; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.MapSchema; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.responses.ApiResponse; import org.testng.annotations.Test; import static io.swagger.v3.core.util.TestUtils.normalizeLineEnds; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class MapPropertyDeserializerTest { private static final String json = "{\n" + " \"tags\": [\n" + " \"store\"\n" + " ],\n" + " \"summary\": \"Returns pet inventories by status\",\n" + " \"description\": \"Returns a map of status codes to quantities\",\n" + " \"operationId\": \"getInventory\",\n" + " \"produces\": [\n" + " \"application/json\"\n" + " ],\n" + " \"parameters\": [],\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"successful operation\",\n" + " \"content\": {\n" + " \"*/*\": {\n" + " \"schema\": {\n" + " \"type\": \"object\",\n" + " \"x-foo\": \"vendor x\",\n" + " \"additionalProperties\": {\n" + " \"type\": \"integer\",\n" + " \"format\": \"int32\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"security\": [\n" + " {\n" + " \"api_key\": []\n" + " }\n" + " ]\n" + "}"; private static final String jsonAdditionalPropertiesBoolean = "{\n" + " \"tags\": [\n" + " \"store\"\n" + " ],\n" + " \"summary\": \"Returns pet inventories by status\",\n" + " \"description\": \"Returns a map of status codes to quantities\",\n" + " \"operationId\": \"getInventory\",\n" + " \"produces\": [\n" + " \"application/json\"\n" + " ],\n" + " \"parameters\": [],\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"successful operation\",\n" + " \"content\": {\n" + " \"*/*\": {\n" + " \"schema\": {\n" + " \"type\": \"object\",\n" + " \"x-foo\": \"vendor x\",\n" + " \"additionalProperties\": false\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"security\": [\n" + " {\n" + " \"api_key\": []\n" + " }\n" + " ]\n" + "}"; private static final String jsonAdditionalPropertiesBooleanTrue = "{\n" + " \"tags\": [\n" + " \"store\"\n" + " ],\n" + " \"summary\": \"Returns pet inventories by status\",\n" + " \"description\": \"Returns a map of status codes to quantities\",\n" + " \"operationId\": \"getInventory\",\n" + " \"produces\": [\n" + " \"application/json\"\n" + " ],\n" + " \"parameters\": [],\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"successful operation\",\n" + " \"content\": {\n" + " \"*/*\": {\n" + " \"schema\": {\n" + " \"type\": \"object\",\n" + " \"x-foo\": \"vendor x\",\n" + " \"additionalProperties\": true\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"security\": [\n" + " {\n" + " \"api_key\": []\n" + " }\n" + " ]\n" + "}"; @Test(description = "it should deserialize a response per #1349") public void testMapDeserialization() throws Exception { Operation operation = Json.mapper().readValue(json, Operation.class); ApiResponse response = operation.getResponses().get("200"); assertNotNull(response); Schema responseSchema = response.getContent().get("*/*").getSchema(); assertNotNull(responseSchema); assertTrue(responseSchema instanceof MapSchema); MapSchema mp = (MapSchema) responseSchema; assertTrue(mp.getAdditionalProperties() instanceof IntegerSchema); } @Test(description = "it should deserialize a boolean additionalProperties") public void testBooleanAdditionalPropertiesDeserialization() throws Exception { Operation operation = Json.mapper().readValue(jsonAdditionalPropertiesBoolean, Operation.class); ApiResponse response = operation.getResponses().get("200"); assertNotNull(response); Schema responseSchema = response.getContent().get("*/*").getSchema(); assertNotNull(responseSchema); assertTrue(responseSchema instanceof ObjectSchema); assertTrue(responseSchema.getAdditionalProperties() instanceof Boolean); assertFalse((Boolean)responseSchema.getAdditionalProperties()); operation = Json.mapper().readValue(jsonAdditionalPropertiesBooleanTrue, Operation.class); response = operation.getResponses().get("200"); assertNotNull(response); responseSchema = response.getContent().get("*/*").getSchema(); assertNotNull(responseSchema); assertTrue(responseSchema instanceof MapSchema); assertTrue(responseSchema.getAdditionalProperties() instanceof Boolean); assertTrue((Boolean)responseSchema.getAdditionalProperties()); } @Test(description = "it should serialize a boolean additionalProperties") public void testBooleanAdditionalPropertiesSerialization() throws Exception { Operation operation = Json.mapper().readValue(json, Operation.class); ApiResponse response = operation.getResponses().get("200"); assertNotNull(response); Schema responseSchema = response.getContent().get("*/*").getSchema(); Schema schema = new ObjectSchema().additionalProperties(true); assertEquals(normalizeLineEnds(Json.pretty(schema)), "{\n" + " \"type\" : \"object\",\n" + " \"additionalProperties\" : true\n" + "}"); schema = new ObjectSchema().additionalProperties(responseSchema); assertEquals(normalizeLineEnds(Json.pretty(schema)), "{\n" + " \"type\" : \"object\",\n" + " \"additionalProperties\" : {\n" + " \"type\" : \"object\",\n" + " \"additionalProperties\" : {\n" + " \"type\" : \"integer\",\n" + " \"format\" : \"int32\"\n" + " },\n" + " \"x-foo\" : \"vendor x\"\n" + " }\n" + "}"); } @Test(description = "vendor extensions should be included with object type") public void testMapDeserializationVendorExtensions() throws Exception { Operation operation = Json.mapper().readValue(json, Operation.class); ApiResponse response = operation.getResponses().get("200"); assertNotNull(response); Schema responseSchema = response.getContent().get("*/*").getSchema(); assertNotNull(responseSchema); MapSchema mp = (MapSchema) responseSchema; assertTrue(mp.getExtensions().size() > 0); assertNotNull(mp.getExtensions().get("x-foo")); assertEquals(mp.getExtensions().get("x-foo"), "vendor x"); } @Test(description = "it should read an example within an inlined schema") public void testIssue1261InlineSchemaExample() throws Exception { Operation operation = Yaml.mapper().readValue( " responses:\n" + " \"200\":\n" + " content:\n" + " '*/*':\n" + " description: OK\n" + " schema:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int32\n" + " name:\n" + " type: string\n" + " required: [id, name]\n" + " example: ok", Operation.class); ApiResponse response = operation.getResponses().get("200"); assertNotNull(response); Schema schema = response.getContent().get("*/*").getSchema(); Object example = schema.getExample(); assertNotNull(example); assertTrue(example instanceof String); assertEquals(example, "ok"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/properties/PropertyDeserializerTest.java ================================================ package io.swagger.v3.core.deserialization.properties; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.math.BigDecimal; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class PropertyDeserializerTest { @Test public void deserializeParameterWithMinimumMaximumValues() throws Exception { String json = "{\n" + " \"in\": \"query\",\n" + " \"type\": \"integer\",\n" + " \"format\": \"int32\",\n" + " \"minimum\": 32,\n" + " \"maximum\": 100\n" + "}"; Schema property = Json.mapper().readValue(json, Schema.class); assertTrue(property instanceof IntegerSchema); IntegerSchema ip = (IntegerSchema) property; assertEquals(ip.getMinimum(), new BigDecimal("32")); assertEquals(ip.getMaximum(), new BigDecimal("100")); } @Test public void deserializePropertyWithMinimumMaximumValues() throws Exception { String json = "{\n" + " \"type\": \"integer\",\n" + " \"format\": \"int32\",\n" + " \"minimum\": 32,\n" + " \"maximum\": 100\n" + "}"; Schema param = Json.mapper().readValue(json, Schema.class); IntegerSchema ip = (IntegerSchema) param; assertEquals(ip.getMinimum(), new BigDecimal("32")); assertEquals(ip.getMaximum(), new BigDecimal("100")); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/SpecFilterTest.java ================================================ package io.swagger.v3.core.filter; import com.google.common.collect.Sets; import io.swagger.v3.core.filter.resources.ChangeGetOperationsFilter; import io.swagger.v3.core.filter.resources.InternalModelPropertiesRemoverFilter; import io.swagger.v3.core.filter.resources.NoGetOperationsFilter; import io.swagger.v3.core.filter.resources.NoOpOperationsFilter; import io.swagger.v3.core.filter.resources.NoOpenAPIFilter; import io.swagger.v3.core.filter.resources.NoParametersWithoutQueryInFilter; import io.swagger.v3.core.filter.resources.NoPathItemFilter; import io.swagger.v3.core.filter.resources.NoPetOperationsFilter; import io.swagger.v3.core.filter.resources.NoPetRefSchemaFilter; import io.swagger.v3.core.filter.resources.RemoveInternalParamsFilter; import io.swagger.v3.core.filter.resources.RemoveUnreferencedDefinitionsFilter; import io.swagger.v3.core.filter.resources.ReplaceGetOperationsFilter; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.tags.Tag; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import java.io.IOException; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; public class SpecFilterTest { private static final Logger LOGGER = LoggerFactory.getLogger(SpecFilterTest.class); private static final String RESOURCE_RECURSIVE_MODELS = "specFiles/recursivemodels.json"; private static final String RESOURCE_PATH = "specFiles/petstore-3.0-v2.json"; private static final String RESOURCE_PATH_3303 = "specFiles/petstore-3.0-v2-ticket-3303.json"; private static final String RESOURCE_WITH_REF_DEFINITION_4737 = "specFiles/3.1.0/issue-4737-3.1.yaml"; private static final String RESOURCE_WITH_REFERRED_DEFINITIONS= "specFiles/3.1.0/specWithReferredSchemas-3.1.yaml"; private static final String RESOURCE_PATH_LIST = "specFiles/3.1.0/list-3.1.json"; private static final String RESOURCE_PATH_COMPOSED_SCHEMA = "specFiles/3.1.0/composed-schema-3.1.json"; private static final String RESOURCE_REFERRED_SCHEMAS = "specFiles/petstore-3.0-referred-schemas.json"; private static final String RESOURCE_PATH_WITHOUT_MODELS = "specFiles/petstore-3.0-v2_withoutModels.json"; private static final String RESOURCE_DEPRECATED_OPERATIONS = "specFiles/deprecatedoperationmodel.json"; private static final String CHANGED_OPERATION_ID = "Changed Operation"; private static final String CHANGED_OPERATION_DESCRIPTION = "Changing some attributes of the operation"; private static final String NEW_OPERATION_ID = "New Operation"; private static final String NEW_OPERATION_DESCRIPTION = "Replaced Operation"; private static final String QUERY = "query"; private static final String PET_MODEL = "Pet"; private static final String TAG_MODEL = "/Tag"; private static final String PET_TAG = "pet"; private static final String STORE_TAG = "store"; private static final String USER_TAG = "user"; @Test(description = "it should clone everything") public void cloneEverything() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); final OpenAPI filtered = new SpecFilter().filter(openAPI, new NoOpOperationsFilter(), null, null, null); assertEquals(Json.pretty(filtered), Json.pretty(openAPI)); } @Test(description = "it should filter away get operations in a resource") public void filterAwayGetOperations() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); final NoGetOperationsFilter filter = new NoGetOperationsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, filter, null, null, null); if (filtered.getPaths() != null) { for (Map.Entry entry : filtered.getPaths().entrySet()) { assertNull(entry.getValue().getGet()); } } else { fail("paths should not be null"); } } @Test(description = "it should filter away the pet resource") public void filterAwayPetResource() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); final NoPetOperationsFilter filter = new NoPetOperationsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, filter, null, null, null); if (filtered.getPaths() != null) { for (Map.Entry entry : filtered.getPaths().entrySet()) { assertNull(entry.getValue().getDelete()); assertNull(entry.getValue().getPost()); assertNull(entry.getValue().getPut()); assertNull(entry.getValue().getGet()); assertNull(entry.getValue().getHead()); assertNull(entry.getValue().getOptions()); } } else { fail("paths should not be null"); } } @Test(description = "it should replace away with a new operation") public void replaceGetResources() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); OpenAPI filter = new SpecFilter().filter(openAPI, new ReplaceGetOperationsFilter(), null, null, null); assertOperations(filter, NEW_OPERATION_ID, NEW_OPERATION_DESCRIPTION); } @Test(description = "it should change away with a new operation") public void changeGetResources() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); OpenAPI filter = new SpecFilter().filter(openAPI, new ChangeGetOperationsFilter(), null, null, null); assertOperations(filter, CHANGED_OPERATION_ID, CHANGED_OPERATION_DESCRIPTION); } private void assertOperations(OpenAPI filtered, String operationId, String description) { if (filtered.getPaths() != null) { for (Map.Entry entry : filtered.getPaths().entrySet()) { Operation get = entry.getValue().getGet(); if (get != null) { assertEquals(get.getOperationId(), operationId); assertEquals(get.getDescription(), description); } } } else { fail("paths should not be null"); } } @Test(description = "it should filter an openAPI object") public void filterAwayOpenAPI() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); final OpenAPI filtered = new SpecFilter().filter(openAPI, new NoOpenAPIFilter(), null, null, null); assertNull(filtered); } @Test(description = "it should filter any PathItem objects without Ref") public void filterAwayPathItemWithoutRef() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); final OpenAPI filtered = new SpecFilter().filter(openAPI, new NoPathItemFilter(), null, null, null); assertEquals(0, filtered.getPaths().size()); } @Test(description = "it should filter any query parameter") public void filterAwayQueryParameters() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); final OpenAPI filtered = new SpecFilter().filter(openAPI, new NoParametersWithoutQueryInFilter(), null, null, null); if (filtered.getPaths() != null) { for (Map.Entry entry : filtered.getPaths().entrySet()) { validateParameters(entry.getValue().getGet()); validateParameters(entry.getValue().getPost()); validateParameters(entry.getValue().getPut()); validateParameters(entry.getValue().getPatch()); validateParameters(entry.getValue().getHead()); validateParameters(entry.getValue().getDelete()); validateParameters(entry.getValue().getOptions()); } } } private void validateParameters(Operation operation) { if (operation != null && operation.getParameters() != null) { for (Parameter parameter : operation.getParameters()) { assertNotEquals(QUERY, parameter.getIn()); } } } @Test(description = "it should clone everything concurrently") public void cloneEverythingConcurrent() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); ThreadGroup tg = new ThreadGroup("SpecFilterTest" + "|" + System.currentTimeMillis()); final Map filteredMap = new ConcurrentHashMap<>(); for (int i = 0; i < 10; i++) { final int id = i; new Thread(tg, "SpecFilterTest") { public void run() { try { filteredMap.put("filtered " + id, new SpecFilter().filter(openAPI, new NoOpOperationsFilter(), null, null, null)); } catch (Exception e) { LOGGER.error("Failed to filter OpenAPI concurrently", e); } } }.start(); } new Thread(new FailureHandler(tg, filteredMap, openAPI)).start(); } class FailureHandler implements Runnable { ThreadGroup tg; Map filteredMap; private OpenAPI openAPI; private FailureHandler(ThreadGroup tg, Map filteredMap, OpenAPI openAPI) { this.tg = tg; this.filteredMap = filteredMap; this.openAPI = openAPI; } @Override public void run() { try { Thread[] thds = new Thread[tg.activeCount()]; tg.enumerate(thds); for (Thread t : thds) { if (t != null) { t.join(10000); } } } catch (Exception e) { LOGGER.error("Interrupted while waiting for filtering threads to complete", e); } for (OpenAPI filtered : filteredMap.values()) { assertEquals(Json.pretty(openAPI), Json.pretty(filtered)); } } } @Test(description = "it should clone everything from JSON without models") public void cloneWithoutModels() throws IOException { final String json = ResourceUtils.loadClassResource(getClass(), RESOURCE_PATH_WITHOUT_MODELS); final OpenAPI openAPI = Json.mapper().readValue(json, OpenAPI.class); final OpenAPI filtered = new SpecFilter().filter(openAPI, new NoOpOperationsFilter(), null, null, null); SerializationMatchers.assertEqualsToJson(filtered, json); } @Test public void shouldRemoveBrokenRefs() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); openAPI.getPaths().get("/pet/{petId}").getGet().getResponses().getDefault().getHeaders().remove("X-Rate-Limit-Limit"); assertNotNull(openAPI.getComponents().getSchemas().get("PetHeader")); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertNull(filtered.getComponents().getSchemas().get("PetHeader")); assertNotNull(filtered.getComponents().getSchemas().get("Category")); assertNotNull(filtered.getComponents().getSchemas().get("Pet")); } @Test public void shouldRemoveBrokenNestedRefs() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH_3303); openAPI.getPaths().get("/pet/{petId}").getGet().getResponses().getDefault().getHeaders().remove("X-Rate-Limit-Limit"); assertNotNull(openAPI.getComponents().getSchemas().get("PetHeader")); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertNull(filtered.getComponents().getSchemas().get("PetHeader")); assertNull(filtered.getComponents().getSchemas().get("Bar")); assertNotNull(filtered.getComponents().getSchemas().get("Category")); assertNotNull(filtered.getComponents().getSchemas().get("Pet")); assertNotNull(filtered.getComponents().getSchemas().get("Foo")); assertNotNull(filtered.getComponents().getSchemas().get("allOfChild")); assertNotNull(filtered.getComponents().getSchemas().get("anyOfChild")); assertNotNull(filtered.getComponents().getSchemas().get("oneOfChild")); assertNotNull(filtered.getComponents().getSchemas().get("allOfparentA")); assertNotNull(filtered.getComponents().getSchemas().get("allOfparentB")); assertNotNull(filtered.getComponents().getSchemas().get("anyOfparentA")); assertNotNull(filtered.getComponents().getSchemas().get("anyOfparentB")); assertNotNull(filtered.getComponents().getSchemas().get("oneOfparentA")); assertNotNull(filtered.getComponents().getSchemas().get("oneOfparentB")); assertNotNull(filtered.getComponents().getSchemas().get("oneOfNestedParentA")); assertNotNull(filtered.getComponents().getSchemas().get("oneOfNestedParentB")); assertNotNull(filtered.getComponents().getSchemas().get("discriminatorParent")); assertNotNull(filtered.getComponents().getSchemas().get("discriminatorMatchedChildA")); assertNotNull(filtered.getComponents().getSchemas().get("discriminatorRefProperty")); assertNotNull(filtered.getComponents().getSchemas().get("discriminatorParentRefProperty")); assertNotNull(filtered.getComponents().getSchemas().get("discriminatorMatchedChildB")); } @Test public void shouldRemoveBrokenNestedRefsKeepArray() throws IOException { final OpenAPI openAPI = getOpenAPI31(RESOURCE_PATH_LIST); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertEquals(filtered.getComponents().getSchemas().size(), 2, "Expected to have parent and child list schemas"); assertTrue(filtered.getComponents().getSchemas().containsKey("SomeChildObject"), "Schemas should contains child list"); } @Test public void shouldRemoveBrokenNestedRefsKeepComposedSchemas() throws IOException { final OpenAPI openAPI = getOpenAPI31(RESOURCE_PATH_COMPOSED_SCHEMA); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertEquals(filtered.getComponents().getSchemas().size(), 5, "Expected to have parent and abstract child with both implementations schemas"); assertTrue(filtered.getComponents().getSchemas().containsKey("SomeChild1ImplObject"), "Schemas should contains child 1 implementation"); assertTrue(filtered.getComponents().getSchemas().containsKey("SomeChild2ImplObject"), "Schemas should contains child 2 implementation"); assertTrue(filtered.getComponents().getSchemas().containsKey("SomeChildObject"), "Schemas should contains child abstract parent"); assertTrue(filtered.getComponents().getSchemas().containsKey("PatternPropertiesReferencedObject"), "Schemas should contains pattern properties referenced schema"); } @Test public void shouldNotRemoveGoodRefs() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); assertNotNull(openAPI.getComponents().getSchemas().get("PetHeader")); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertNotNull(filtered.getComponents().getSchemas().get("PetHeader")); assertNotNull(filtered.getComponents().getSchemas().get("Category")); } @Test(description = "it should filter any Pet Ref in Schemas") public void filterAwayPetRefInSchemas() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); final OpenAPI filtered = new SpecFilter().filter(openAPI, new NoPetRefSchemaFilter(), null, null, null); validateSchemasInComponents(filtered.getComponents(), PET_MODEL); } private void validateSchemasInComponents(Components components, String model) { if (components != null) { if (components.getSchemas() != null) { components.getSchemas().forEach((k, v) -> assertNotEquals(model, k)); } } } @Test(description = "it should filter away secret parameters") public void filterAwaySecretParameters() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); final RemoveInternalParamsFilter filter = new RemoveInternalParamsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, filter, null, null, null); if (filtered.getPaths() != null) { for (Map.Entry entry : filtered.getPaths().entrySet()) { final Operation get = entry.getValue().getGet(); if (get != null) { for (Parameter param : get.getParameters()) { final String description = param.getDescription(); if (StringUtils.isNotBlank(description)) { assertFalse(description.startsWith("secret")); } } } } } else { fail("paths should not be null"); } } @Test(description = "it should filter away internal model properties") public void filterAwayInternalModelProperties() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); final InternalModelPropertiesRemoverFilter filter = new InternalModelPropertiesRemoverFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, filter, null, null, null); for (Map.Entry entry : filtered.getComponents().getSchemas().entrySet()) { for (String propName : (Set) entry.getValue().getProperties().keySet()) { assertFalse(propName.startsWith("_")); } } } @Test(description = "it should retain non-broken reference model composed properties") public void retainNonBrokenReferenceModelComposedProperties() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_REFERRED_SCHEMAS); assertNotNull(openAPI.getComponents().getSchemas().get("User")); final NoOpOperationsFilter noOperationsFilter = new NoOpOperationsFilter(); OpenAPI filtered = new SpecFilter().filter(openAPI, noOperationsFilter, null, null, null); assertNotNull(filtered.getComponents().getSchemas().get("User")); final RemoveUnreferencedDefinitionsFilter refFilter = new RemoveUnreferencedDefinitionsFilter(); filtered = new SpecFilter().filter(openAPI, refFilter, null, null, null); assertNotNull(filtered.getComponents().getSchemas().get("User")); assertNotNull(filtered.getComponents().getSchemas().get("Pet")); } @Test(description = "recursive models, e.g. A-> A or A-> B and B -> A should not result in stack overflow") public void removeUnreferencedDefinitionsOfRecuriveModels() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_RECURSIVE_MODELS); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertNotNull(filtered.getComponents().getSchemas().get("SelfReferencingModel")); assertNotNull(filtered.getComponents().getSchemas().get("IndirectRecursiveModelA")); assertNotNull(filtered.getComponents().getSchemas().get("IndirectRecursiveModelB")); } @Test(description = "broken references should not result in NPE") public void removeUnreferencedModelOverride() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_REFERRED_SCHEMAS); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertNotNull(filtered.getComponents().getSchemas().get("Order")); } @Test(description = "Retain models referenced from additonalProperties") public void retainModelsReferencesFromAdditionalProperties() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_REFERRED_SCHEMAS); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertNotNull(filtered.getComponents().getSchemas().get("Order")); assertNotNull(filtered.getComponents().getSchemas().get("ReferredOrder")); } @Test(description = "Clone should retain any 'deperecated' flags present on operations") public void cloneRetainDeperecatedFlags() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_DEPRECATED_OPERATIONS); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); Operation operation = filtered.getPaths().get("/test").getGet(); Boolean deprectedFlag = operation.getDeprecated(); assertNotNull(deprectedFlag); assertEquals(deprectedFlag, Boolean.TRUE); } @Test(description = "it should contain all tags in the top level OpenAPI object") public void shouldContainAllTopLevelTags() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_REFERRED_SCHEMAS); final NoOpOperationsFilter filter = new NoOpOperationsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, filter, null, null, null); assertEquals(getTagNames(filtered), Sets.newHashSet(PET_TAG, USER_TAG, STORE_TAG)); } @Test(description = "it should not contain user tags in the top level OpenAPI object") public void shouldNotContainTopLevelUserTags() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_REFERRED_SCHEMAS); final NoPetOperationsFilter filter = new NoPetOperationsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, filter, null, null, null); assertEquals(getTagNames(filtered), Sets.newHashSet(USER_TAG, STORE_TAG)); } @Test(description = "it should filter with null definitions") public void filterWithNullDefinitions() throws IOException { final OpenAPI openAPI = getOpenAPI(RESOURCE_PATH); openAPI.getComponents().setSchemas(null); final InternalModelPropertiesRemoverFilter filter = new InternalModelPropertiesRemoverFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, filter, null, null, null); assertNotNull(filtered); } @Test(description = "RemoveUnreferencedDefinitionsFilter should not remove schema definition if ref used in Webhook") public void testTicket4737() throws IOException { final OpenAPI openAPI = getOpenAPIYaml31(RESOURCE_WITH_REF_DEFINITION_4737); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertNotNull(filtered.getComponents().getSchemas().get("RequestDto")); } @Test public void shouldNotRemoveUsedDefinitions() throws IOException { final OpenAPI openAPI = getOpenAPIYaml31(RESOURCE_WITH_REFERRED_DEFINITIONS); final RemoveUnreferencedDefinitionsFilter remover = new RemoveUnreferencedDefinitionsFilter(); final OpenAPI filtered = new SpecFilter().filter(openAPI, remover, null, null, null); assertNotNull(filtered.getComponents().getSchemas().get("ResponseDefinition")); assertNotNull(filtered.getComponents().getSchemas().get("WebhookResponseDefinition")); assertNotNull(filtered.getComponents().getSchemas().get("WebhookOperationDefinition")); assertNotNull(filtered.getComponents().getSchemas().get("RequestBodyDefinition")); assertNotNull(filtered.getComponents().getSchemas().get("ParameterDefinition")); assertNotNull(filtered.getComponents().getSchemas().get("HeaderDefinition")); assertNotNull(filtered.getComponents().getSchemas().get("CallbackDefinition")); assertNotNull(filtered.getComponents().getSchemas().get("PathItemDefinition")); assertNull(filtered.getComponents().getSchemas().get("UnusedDefinition")); } private Set getTagNames(OpenAPI openAPI) { Set result = new HashSet<>(); if (openAPI.getTags() != null) { for (Tag item : openAPI.getTags()) { result.add(item.getName()); } } return result; } private OpenAPI getOpenAPI(String path) throws IOException { final String json = ResourceUtils.loadClassResource(getClass(), path); return Json.mapper().readValue(json, OpenAPI.class); } private OpenAPI getOpenAPI31(String path) throws IOException { final String json = ResourceUtils.loadClassResource(getClass(), path); return Json31.mapper().readValue(json, OpenAPI.class); } private OpenAPI getOpenAPIYaml(String path) throws IOException { final String yaml = ResourceUtils.loadClassResource(getClass(), path); return Yaml.mapper().readValue(yaml, OpenAPI.class); } private OpenAPI getOpenAPIYaml31(String path) throws IOException { final String yaml = ResourceUtils.loadClassResource(getClass(), path); return Yaml31.mapper().readValue(yaml, OpenAPI.class); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/ChangeGetOperationsFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.Operation; import java.util.List; import java.util.Map; import java.util.Optional; /** * Sample filter to avoid all get operations for the resource **/ public class ChangeGetOperationsFilter extends AbstractSpecFilter { private static final String GET = "GET"; private static final String CHANGED_OPERATION_ID = "Changed Operation"; private static final String CHANGED_OPERATION_DESCRIPTION = "Changing some attributes of the operation"; @Override public Optional filterOperation(Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if (GET.equals(api.getMethod())) { return Optional.of(operation.operationId(CHANGED_OPERATION_ID).description(CHANGED_OPERATION_DESCRIPTION)); } return Optional.of(operation); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/InternalModelPropertiesRemoverFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import java.util.List; import java.util.Map; import java.util.Optional; /** * Sample filter to model properties starting with "_" unless a header * "super-user" is passed */ public class InternalModelPropertiesRemoverFilter extends AbstractSpecFilter { @Override public Optional filterSchemaProperty(Schema property, Schema schema, String propName, Map> params, Map cookies, Map> headers) { if (StringUtils.isNotBlank(property.getName()) && property.getName().startsWith("_")) { if (headers != null && headers.containsKey("super-user")) { return Optional.of(property); } return Optional.empty(); } else { return Optional.of(property); } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/NoCategoryRefSchemaFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import java.util.List; import java.util.Map; import java.util.Optional; public class NoCategoryRefSchemaFilter extends AbstractSpecFilter { private static final String MODEL = "Category"; @Override public Optional filterSchemaProperty(Schema property, Schema schema, String propName, Map> params, Map cookies, Map> headers) { if (schema == null || StringUtils.isBlank(schema.get$ref())) { return Optional.of(schema); } if (schema.get$ref().contains(MODEL)) { return Optional.empty(); } return Optional.of(schema); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/NoGetOperationsFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.Operation; import java.util.List; import java.util.Map; import java.util.Optional; /** * Sample filter to avoid all get operations for the resource **/ public class NoGetOperationsFilter extends AbstractSpecFilter { private static final String GET = "GET"; @Override public Optional filterOperation(Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if (GET.equals(api.getMethod())) { return Optional.empty(); } return Optional.of(operation); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/NoOpOperationsFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; /** * Does nothing **/ public class NoOpOperationsFilter extends AbstractSpecFilter { } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/NoOpenAPIFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.oas.models.OpenAPI; import java.util.List; import java.util.Map; import java.util.Optional; /** * Does nothing **/ public class NoOpenAPIFilter extends AbstractSpecFilter { public static final String VERSION = "3.0.1"; @Override public Optional filterOpenAPI(OpenAPI openAPI, Map> params, Map cookies, Map> headers) { if (VERSION.equals(openAPI.getOpenapi())) { return Optional.empty(); } return Optional.of(openAPI); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/NoParametersWithoutQueryInFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.parameters.Parameter; import java.util.List; import java.util.Map; import java.util.Optional; /** * Does nothing **/ public class NoParametersWithoutQueryInFilter extends AbstractSpecFilter { private static final String QUERY_IN = "query"; @Override public Optional filterParameter(Parameter parameter, Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if (QUERY_IN.equals(parameter.getIn())) { return Optional.empty(); } return Optional.of(parameter); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/NoPathItemFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.PathItem; import org.apache.commons.lang3.StringUtils; import java.util.List; import java.util.Map; import java.util.Optional; /** * Does nothing **/ public class NoPathItemFilter extends AbstractSpecFilter { @Override public Optional filterPathItem(PathItem pathItem, ApiDescription api, Map> params, Map cookies, Map> headers) { if (StringUtils.isBlank(pathItem.get$ref())) { return Optional.empty(); } return Optional.of(pathItem); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/NoPetOperationsFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.Operation; import java.util.List; import java.util.Map; import java.util.Optional; /** * Sample filter to avoid all resources for the /user resource **/ public class NoPetOperationsFilter extends AbstractSpecFilter { public static final String PET_RESOURCE = "/pet"; @Override public Optional filterOperation(Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if (api.getPath().startsWith(PET_RESOURCE)) { return Optional.empty(); } return Optional.of(operation); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/NoPetRefSchemaFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import java.util.List; import java.util.Map; import java.util.Optional; public class NoPetRefSchemaFilter extends AbstractSpecFilter { private static final String MODEL = "Pet"; @Override public Optional filterSchema(Schema schema, Map> params, Map cookies, Map> headers) { if (schema == null || StringUtils.isBlank(schema.getXml().getName())) { return Optional.of(schema); } if (schema.getXml().getName().equals(MODEL)) { return Optional.empty(); } return Optional.of(schema); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/NoTagRefSchemaPropertyFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import java.util.List; import java.util.Map; import java.util.Optional; public class NoTagRefSchemaPropertyFilter extends AbstractSpecFilter { private static final String MODEL = "Tag"; @Override public Optional filterSchemaProperty(Schema property, Schema schema, String propName, Map> params, Map cookies, Map> headers) { if (property == null || StringUtils.isBlank(property.get$ref())) { return Optional.of(property); } if (property.get$ref().contains(MODEL)) { return Optional.empty(); } return Optional.of(property); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/RemoveInternalParamsFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.parameters.Parameter; import java.util.List; import java.util.Map; import java.util.Optional; /** * Sample filter to parameters if "internal" has been set and the header * "super-user" is not passed **/ public class RemoveInternalParamsFilter extends AbstractSpecFilter { @Override public Optional filterParameter(Parameter parameter, Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if (parameter.getDescription() != null && parameter.getDescription().startsWith("secret:")) { if (headers != null) { if (headers.containsKey("super-user")) { return Optional.of(parameter); } } return Optional.empty(); } return Optional.of(parameter); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/RemoveUnreferencedDefinitionsFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; /** * signals to remove unreferenced definitions. **/ public class RemoveUnreferencedDefinitionsFilter extends AbstractSpecFilter { @Override public boolean isRemovingUnreferencedDefinitions() { return true; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/filter/resources/ReplaceGetOperationsFilter.java ================================================ package io.swagger.v3.core.filter.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.Operation; import java.util.List; import java.util.Map; import java.util.Optional; /** * Sample filter to avoid all get operations for the resource **/ public class ReplaceGetOperationsFilter extends AbstractSpecFilter { private static final String GET = "GET"; private static final String NEW_OPERATION_ID = "New Operation"; private static final String NEW_OPERATION_DESCRIPTION = "Replaced Operation"; @Override public Optional filterOperation(Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if (GET.equals(api.getMethod())) { return Optional.of(new Operation().description(NEW_OPERATION_DESCRIPTION). operationId(NEW_OPERATION_ID)); } return Optional.of(operation); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/issues/Issue4339Test.java ================================================ package io.swagger.v3.core.issues; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.oas.annotations.media.Schema; import org.testng.annotations.Test; import java.math.BigDecimal; import static org.testng.Assert.*; /** * Reproduces GitHub Issue #4339 * Schema annotation processing isn't working with nullable and "null" example or default value * * Expected behavior: * All data types should respect nullable=true and produce null values in example/default fields * when example="null" or defaultValue="null" is specified. * * Tests both OAS 3.0 and OAS 3.1 specifications. * * @see ... */ public class Issue4339Test { //OAS 3.0 Tests @Test public void testNullableStringWithNullExampleAndDefault_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableStringModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableStringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableStringField"); assertNotNull(nullableStringField, "nullableStringField property should exist"); assertEquals(nullableStringField.getNullable(), Boolean.TRUE, "Field should be nullable"); assertNull(nullableStringField.getExample(), "Example should be null for nullable field with example=\"null\", but got: " + nullableStringField.getExample()); assertNull(nullableStringField.getDefault(), "Default should be null for nullable field with defaultValue=\"null\", but got: " + nullableStringField.getDefault()); } @Test public void testNullableIntegerWithNullExampleAndDefault_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableIntegerModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableIntegerField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableIntegerField"); assertNotNull(nullableIntegerField, "nullableIntegerField property should exist"); assertEquals(nullableIntegerField.getNullable(), Boolean.TRUE, "Field should be nullable"); assertNull(nullableIntegerField.getExample(), "Example should be null for nullable integer field with example=\"null\""); assertNull(nullableIntegerField.getDefault(), "Default should be null for nullable integer field with defaultValue=\"null\""); } @Test public void testNullableBigDecimalWithNullExampleAndDefault_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableBigDecimalModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableBigDecimalField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableBigDecimalField"); assertNotNull(nullableBigDecimalField, "nullableBigDecimalField property should exist"); assertEquals(nullableBigDecimalField.getNullable(), Boolean.TRUE, "Field should be nullable"); assertNull(nullableBigDecimalField.getExample(), "Example should be null for nullable number field with example=\"null\""); assertNull(nullableBigDecimalField.getDefault(), "Default should be null for nullable number field with defaultValue=\"null\""); } @Test public void testNullableBooleanWithNullExampleAndDefault_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableBooleanModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableBooleanField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableBooleanField"); assertNotNull(nullableBooleanField, "nullableBooleanField property should exist"); assertEquals(nullableBooleanField.getNullable(), Boolean.TRUE, "Field should be nullable"); assertNull(nullableBooleanField.getExample(), "Example should be null for nullable boolean field with example=\"null\", but got: " + nullableBooleanField.getExample()); assertNull(nullableBooleanField.getDefault(), "Default should be null for nullable boolean field with defaultValue=\"null\", but got: " + nullableBooleanField.getDefault()); } @Test public void testNullableObjectWithNullExampleAndDefault_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableObjectModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableObjectField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableObjectField"); assertNotNull(nullableObjectField, "nullableObjectField property should exist"); assertEquals(nullableObjectField.getNullable(), Boolean.TRUE, "Field should be nullable"); assertNull(nullableObjectField.getExample(), "Object example should be null"); assertNull(nullableObjectField.getDefault(), "Object default should be null"); } // OAS 3.1 Tests @Test public void testNullableStringWithNullExampleAndDefault_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableStringModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableStringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableStringField"); assertNotNull(nullableStringField, "nullableStringField property should exist"); assertTrue(isNullableInOAS31(nullableStringField), "Field should be nullable (type array should contain 'null')"); assertNull(nullableStringField.getExample(), "Example should be null for nullable field with example=\"null\", but got: " + nullableStringField.getExample()); assertNull(nullableStringField.getDefault(), "Default should be null for nullable field with defaultValue=\"null\", but got: " + nullableStringField.getDefault()); } @Test public void testNullableIntegerWithNullExampleAndDefault_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableIntegerModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableIntegerField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableIntegerField"); assertNotNull(nullableIntegerField, "nullableIntegerField property should exist"); assertTrue(isNullableInOAS31(nullableIntegerField), "Field should be nullable (type array should contain 'null')"); assertNull(nullableIntegerField.getExample(), "Example should be null for nullable integer field with example=\"null\""); assertNull(nullableIntegerField.getDefault(), "Default should be null for nullable integer field with defaultValue=\"null\""); } @Test public void testNullableBigDecimalWithNullExampleAndDefault_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableBigDecimalModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableBigDecimalField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableBigDecimalField"); assertNotNull(nullableBigDecimalField, "nullableBigDecimalField property should exist"); assertTrue(isNullableInOAS31(nullableBigDecimalField), "Field should be nullable (type array should contain 'null')"); assertNull(nullableBigDecimalField.getExample(), "Example should be null for nullable number field with example=\"null\""); assertNull(nullableBigDecimalField.getDefault(), "Default should be null for nullable number field with defaultValue=\"null\""); } @Test public void testNullableBooleanWithNullExampleAndDefault_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableBooleanModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableBooleanField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableBooleanField"); assertNotNull(nullableBooleanField, "nullableBooleanField property should exist"); assertTrue(isNullableInOAS31(nullableBooleanField), "Field should be nullable (type array should contain 'null')"); assertNull(nullableBooleanField.getExample(), "Example should be null for nullable boolean field with example=\"null\", but got: " + nullableBooleanField.getExample()); assertNull(nullableBooleanField.getDefault(), "Default should be null for nullable boolean field with defaultValue=\"null\", but got: " + nullableBooleanField.getDefault()); } @Test public void testNullableObjectWithNullExampleAndDefault_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableObjectModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema nullableObjectField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableObjectField"); assertNotNull(nullableObjectField, "nullableObjectField property should exist"); assertTrue(isNullableInOAS31(nullableObjectField), "Field should be nullable (type array should contain 'null')"); assertNull(nullableObjectField.getExample(), "Object example should be null"); assertNull(nullableObjectField.getDefault(), "Object default should be null"); } // Tests for omitted example/default values @Test public void testNullableWithoutExampleOrDefault_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableWithoutExampleDefaultModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema stringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("stringField"); assertNotNull(stringField, "stringField property should exist"); assertEquals(stringField.getNullable(), Boolean.TRUE, "Field should be nullable"); assertNull(stringField.getExample(), "Example should be null (not set)"); assertNull(stringField.getDefault(), "Default should be null (not set)"); io.swagger.v3.oas.models.media.Schema integerField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("integerField"); assertNotNull(integerField, "integerField property should exist"); assertEquals(integerField.getNullable(), Boolean.TRUE, "Field should be nullable"); assertNull(integerField.getExample(), "Example should be null (not set)"); assertNull(integerField.getDefault(), "Default should be null (not set)"); io.swagger.v3.oas.models.media.Schema booleanField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("booleanField"); assertNotNull(booleanField, "booleanField property should exist"); assertEquals(booleanField.getNullable(), Boolean.TRUE, "Field should be nullable"); assertNull(booleanField.getExample(), "Example should be null (not set)"); assertNull(booleanField.getDefault(), "Default should be null (not set)"); } @Test public void testNullableWithoutExampleOrDefault_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableWithoutExampleDefaultModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema stringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("stringField"); assertNotNull(stringField, "stringField property should exist"); assertTrue(isNullableInOAS31(stringField), "Field should be nullable (type array should contain 'null')"); assertNull(stringField.getExample(), "Example should be null (not set)"); assertNull(stringField.getDefault(), "Default should be null (not set)"); io.swagger.v3.oas.models.media.Schema integerField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("integerField"); assertNotNull(integerField, "integerField property should exist"); assertTrue(isNullableInOAS31(integerField), "Field should be nullable (type array should contain 'null')"); assertNull(integerField.getExample(), "Example should be null (not set)"); assertNull(integerField.getDefault(), "Default should be null (not set)"); io.swagger.v3.oas.models.media.Schema booleanField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("booleanField"); assertNotNull(booleanField, "booleanField property should exist"); assertTrue(isNullableInOAS31(booleanField), "Field should be nullable (type array should contain 'null')"); assertNull(booleanField.getExample(), "Example should be null (not set)"); assertNull(booleanField.getDefault(), "Default should be null (not set)"); } @Test public void testNullableWithDefaultOnly_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableWithDefaultOnlyModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema stringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("stringField"); assertNotNull(stringField, "stringField property should exist"); assertNull(stringField.getExample(), "Example should be null (not set)"); assertEquals(stringField.getDefault(), "defaultValue", "Default should be 'defaultValue'"); } @Test public void testNullableWithExampleOnly_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableWithExampleOnlyModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema stringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("stringField"); assertNotNull(stringField, "stringField property should exist"); assertEquals(stringField.getExample(), "exampleValue", "Example should be 'exampleValue'"); assertNull(stringField.getDefault(), "Default should be null (not set)"); } // ========== Tests for nullable=false with example/default="null" ========== /** * Test non-nullable field with example="null" and defaultValue="null" - OAS 3.0 * When nullable=false, "null" string should NOT be parsed as null value * It should be treated as the literal string "null" */ @Test public void testNonNullableStringWithNullExampleAndDefault_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NonNullableStringModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema stringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("stringField"); assertNotNull(stringField, "stringField property should exist"); assertNull(stringField.getNullable(), "Field should not have nullable set (or be false)"); // When nullable=false, "null" string should be treated as literal string "null", not null value assertEquals(stringField.getExample(), "null", "Example should be the string \"null\", not null value when nullable=false"); assertEquals(stringField.getDefault(), "null", "Default should be the string \"null\", not null value when nullable=false"); } /** * Test non-nullable field with example="null" and defaultValue="null" - OAS 3.1 * When nullable=false, "null" string should NOT be parsed as null value */ @Test public void testNonNullableStringWithNullExampleAndDefault_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NonNullableStringModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema stringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("stringField"); assertNotNull(stringField, "stringField property should exist"); assertNull(stringField.getNullable(), "Field should not have nullable set in OAS 3.1"); // When nullable=false, "null" string should be treated as literal string "null", not null value assertEquals(stringField.getExample(), "null", "Example should be the string \"null\", not null value when nullable=false"); assertEquals(stringField.getDefault(), "null", "Default should be the string \"null\", not null value when nullable=false"); } /** * Test non-nullable Boolean field - OAS 3.0 */ @Test public void testNonNullableBooleanWithNullExampleAndDefault_OAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NonNullableBooleanModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema booleanField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("booleanField"); assertNotNull(booleanField, "booleanField property should exist"); assertNull(booleanField.getNullable(), "Field should not have nullable set"); assertEquals(booleanField.getExample(), false, "Should convert to false"); assertEquals(booleanField.getDefault(), false, "Should convert to false"); } /** * Test non-nullable Integer field - OAS 3.1 * Should treat "null" as string, not parse to null value */ @Test public void testNonNullableIntegerWithNullExampleAndDefault_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NonNullableIntegerModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema integerField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("integerField"); assertNotNull(integerField, "integerField property should exist"); assertEquals(integerField.getExample(), "null", "Example should be the string \"null\", not null value"); assertEquals(integerField.getDefault(), "null", "Default should be the string \"null\", not null value"); } // ========== Test for Issue #4229 (same root cause as #4339) ========== /** * Test case from Issue #4229: Nullable Integer ignores example value "null" and defaults to 0 * https://github.com/swagger-api/swagger-core/issues/4229 * This should now be fixed by the same changes that fix #4339 */ @Test public void testIssue4229_NullableIntegerWithNullExample() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(Issue4229TestData.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema idSchema = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("id"); assertNotNull(idSchema, "id property should exist"); assertEquals(idSchema.getNullable(), Boolean.TRUE, "Field should be nullable"); // Issue #4229: exampleSetFlag should be true and example should be null, not 0 assertTrue(idSchema.getExampleSetFlag(), "exampleSetFlag should be true when example=\"null\" is set"); assertNull(idSchema.getExample(), "Example should be null, not 0 (fixes issue #4229)"); } // ========== Tests for OAS 3.1 "examples" array field ========== /** * Test OAS 3.1 examples array with null value * In OAS 3.1, there's an "examples" array field in addition to the single "example" field */ @Test public void testNullableStringWithNullInExamplesArray_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableStringWithExamplesModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema stringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("stringField"); assertNotNull(stringField, "stringField property should exist"); assertTrue(isNullableInOAS31(stringField), "Field should be nullable (type array should contain 'null')"); assertNotNull(stringField.getExamples(), "examples array should exist"); assertEquals(stringField.getExamples().size(), 3, "examples array should have 3 elements"); assertTrue(stringField.getExamples().contains("validValue"), "examples should contain 'validValue'"); assertTrue(stringField.getExamples().contains(null), "examples should contain null value"); assertTrue(stringField.getExamples().contains("anotherValue"), "examples should contain 'anotherValue'"); } /** * Test OAS 3.1 examples array with multiple values including null */ @Test public void testNullableIntegerWithMultipleExamplesIncludingNull_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableIntegerWithMultipleExamplesModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema integerField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("integerField"); assertNotNull(integerField, "integerField property should exist"); assertNotNull(integerField.getExamples(), "examples array should exist"); assertEquals(integerField.getExamples().size(), 3, "examples array should have 3 elements"); assertTrue(integerField.getExamples().contains("1"), "examples should contain '1' as string"); assertTrue(integerField.getExamples().contains(null), "examples should contain null value"); assertTrue(integerField.getExamples().contains("100"), "examples should contain '100' as string"); } /** * Test that examples array is NOT set in OAS 3.0 (only OAS 3.1) * * Note: In OAS 3.0, the 'examples' field (plural, as array) is only valid on: * - Parameter Object (parameters[*].examples) - as Map * - Media Type Object (content[media-type].examples) - as Map * - Header Object (headers[*].examples) - as Map * * For Schema objects, OAS 3.0 only supports the singular 'example' field. * The 'examples' array was added to Schema objects in OAS 3.1. */ @Test public void testExamplesArrayNotSetInOAS30() { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableStringWithExamplesModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema stringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("stringField"); assertNotNull(stringField, "stringField property should exist"); assertEquals(stringField.getNullable(), Boolean.TRUE, "Field should be nullable"); assertNull(stringField.getExamples(), "examples array should NOT be set in OAS 3.0"); } /** * Test that when both example and examples are set, only examples is used in OAS 3.1 * The single example field is ignored by design when examples array is present */ @Test public void testExamplesArrayTakesPrecedenceOverExample_OAS31() { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(BothExampleAndExamplesModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); io.swagger.v3.oas.models.media.Schema stringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("stringField"); assertNotNull(stringField, "stringField property should exist"); assertTrue(isNullableInOAS31(stringField), "Field should be nullable (type array should contain 'null')"); assertNull(stringField.getExample(), "example field should be null/not set when examples array is present"); assertNotNull(stringField.getExamples(), "examples array should be set"); assertEquals(stringField.getExamples().size(), 3, "examples array should have 3 elements"); assertTrue(stringField.getExamples().contains("arrayValue1"), "examples should contain 'arrayValue1'"); assertTrue(stringField.getExamples().contains(null), "examples should contain null"); assertTrue(stringField.getExamples().contains("arrayValue3"), "examples should contain 'arrayValue3'"); assertFalse(stringField.getExamples().contains("singleExampleValue"), "examples should NOT contain the value from single example field"); } private boolean isNullableInOAS31(io.swagger.v3.oas.models.media.Schema schema) { if (schema.getTypes() != null && schema.getTypes().contains("null")) { return true; } return false; } // Test model classes public static class NullableStringModel { @Schema(nullable = true, example = "null", defaultValue = "null") private String nullableStringField; public String getNullableStringField() { return nullableStringField; } public void setNullableStringField(String nullableStringField) { this.nullableStringField = nullableStringField; } } public static class NullableIntegerModel { @Schema(nullable = true, example = "null", defaultValue = "null") private Integer nullableIntegerField; public Integer getNullableIntegerField() { return nullableIntegerField; } public void setNullableIntegerField(Integer nullableIntegerField) { this.nullableIntegerField = nullableIntegerField; } } public static class NullableBigDecimalModel { @Schema(nullable = true, example = "null", defaultValue = "null") private BigDecimal nullableBigDecimalField; public BigDecimal getNullableBigDecimalField() { return nullableBigDecimalField; } public void setNullableBigDecimalField(BigDecimal nullableBigDecimalField) { this.nullableBigDecimalField = nullableBigDecimalField; } } public static class NullableBooleanModel { @Schema(nullable = true, example = "null", defaultValue = "null") private Boolean nullableBooleanField; public Boolean getNullableBooleanField() { return nullableBooleanField; } public void setNullableBooleanField(Boolean nullableBooleanField) { this.nullableBooleanField = nullableBooleanField; } } public static class NullableObjectModel { @Schema(nullable = true, example = "null", defaultValue = "null") private Object nullableObjectField; public Object getNullableObjectField() { return nullableObjectField; } public void setNullableObjectField(Object nullableObjectField) { this.nullableObjectField = nullableObjectField; } } public static class NullableWithoutExampleDefaultModel { @Schema(nullable = true) private String stringField; @Schema(nullable = true) private Integer integerField; @Schema(nullable = true) private Boolean booleanField; public String getStringField() { return stringField; } public void setStringField(String stringField) { this.stringField = stringField; } public Integer getIntegerField() { return integerField; } public void setIntegerField(Integer integerField) { this.integerField = integerField; } public Boolean getBooleanField() { return booleanField; } public void setBooleanField(Boolean booleanField) { this.booleanField = booleanField; } } public static class NullableWithDefaultOnlyModel { @Schema(nullable = true, defaultValue = "defaultValue") private String stringField; public String getStringField() { return stringField; } public void setStringField(String stringField) { this.stringField = stringField; } } public static class NullableWithExampleOnlyModel { @Schema(nullable = true, example = "exampleValue") private String stringField; public String getStringField() { return stringField; } public void setStringField(String stringField) { this.stringField = stringField; } } // Test model classes for non-nullable fields with null example/default public static class NonNullableStringModel { @Schema(nullable = false, example = "null", defaultValue = "null") private String stringField; public String getStringField() { return stringField; } public void setStringField(String stringField) { this.stringField = stringField; } } public static class NonNullableBooleanModel { @Schema(nullable = false, example = "null", defaultValue = "null") private Boolean booleanField; public Boolean getBooleanField() { return booleanField; } public void setBooleanField(Boolean booleanField) { this.booleanField = booleanField; } } public static class NonNullableIntegerModel { @Schema(nullable = false, example = "null", defaultValue = "null") private Integer integerField; public Integer getIntegerField() { return integerField; } public void setIntegerField(Integer integerField) { this.integerField = integerField; } } /** * Test model class for Issue #4229 * Matches the exact example from the issue report */ public static class Issue4229TestData { @Schema(nullable = true, example = "null") private Integer id; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } /** * Test model with examples array containing "null" string in OAS 3.1 */ public static class NullableStringWithExamplesModel { @Schema(nullable = true, examples = {"validValue", "null", "anotherValue"}) private String stringField; public String getStringField() { return stringField; } public void setStringField(String stringField) { this.stringField = stringField; } } /** * Test model with examples array containing multiple values including "null" */ public static class NullableIntegerWithMultipleExamplesModel { @Schema(nullable = true, examples = {"1", "null", "100"}) private Integer integerField; public Integer getIntegerField() { return integerField; } public void setIntegerField(Integer integerField) { this.integerField = integerField; } } /** * Test model with both example and examples set * Only examples should be used in the generated OpenAPI */ public static class BothExampleAndExamplesModel { @Schema(nullable = true, example = "singleExampleValue", examples = {"arrayValue1", "null", "arrayValue3"}) private String stringField; public String getStringField() { return stringField; } public void setStringField(String stringField) { this.stringField = stringField; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/issues/Issue4838Test.java ================================================ package io.swagger.v3.core.issues; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.oas.annotations.media.Schema; import org.checkerframework.checker.nullness.qual.NonNull; import org.testng.annotations.Test; import java.math.BigDecimal; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class Issue4838Test { @Test public void defaultValueShouldBeEmptyForStringFieldInOas30() { final ModelConverterContextImpl context = getModelConverterContext(Json.mapper(), false); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableStringModel.class)); io.swagger.v3.oas.models.media.Schema nullableStringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableStringField"); assertNotNull(nullableStringField); assertTrue(nullableStringField.getNullable()); assertNotNull(nullableStringField.getDefault()); assertEquals(nullableStringField.getDefault(), ""); } @Test public void defaultValueShouldBeNullForIntegerFieldInOas30() { final ModelConverterContextImpl context = getModelConverterContext(Json.mapper(), false); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableIntegerModel.class)); io.swagger.v3.oas.models.media.Schema nullableIntegerField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableIntegerField"); assertNotNull(nullableIntegerField); assertTrue(nullableIntegerField.getNullable()); assertNull(nullableIntegerField.getExample()); assertNull(nullableIntegerField.getDefault()); } @Test public void defaultValueShouldBeProvidedFromBigDecimalSchemaForOas30() { final ModelConverterContextImpl context = getModelConverterContext(Json.mapper(), false); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableBigDecimalModel.class)); io.swagger.v3.oas.models.media.Schema nullableBigDecimalField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableBigDecimalField"); System.out.println(nullableBigDecimalField); assertNotNull(nullableBigDecimalField); assertTrue(nullableBigDecimalField.getNullable()); assertNull(nullableBigDecimalField.getExample()); assertEquals(nullableBigDecimalField.getDefault().toString(), "123"); } @Test public void defaultValueShouldBeNullProvidedFromBooleanSchemaForOas30() { final ModelConverterContextImpl context = getModelConverterContext(Json.mapper(), false); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableBooleanModel.class)); io.swagger.v3.oas.models.media.Schema nullableBooleanField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableBooleanField"); assertNotNull(nullableBooleanField); assertTrue(nullableBooleanField.getNullable()); assertNull(nullableBooleanField.getExample()); assertNull(nullableBooleanField.getDefault()); } @Test public void defaultValueShouldBeEmptyForStringFieldInOas31() { final ModelConverterContextImpl context = getModelConverterContext(Json31.mapper(), true); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableStringModel.class)); io.swagger.v3.oas.models.media.Schema nullableStringField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableStringField"); assertNotNull(nullableStringField); assertTrue(isNullableInOAS31(nullableStringField)); assertNotNull(nullableStringField.getDefault()); assertEquals(nullableStringField.getDefault(), ""); } @Test public void defaultValueShouldBeNullForIntegerFieldInOas31() { final ModelConverterContextImpl context = getModelConverterContext(Json31.mapper(), true); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableIntegerModel.class)); io.swagger.v3.oas.models.media.Schema nullableIntegerField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableIntegerField"); assertNotNull(nullableIntegerField); assertTrue(isNullableInOAS31(nullableIntegerField)); assertNull(nullableIntegerField.getExample()); assertNull(nullableIntegerField.getDefault()); } @Test public void defaultValueShouldBeProvidedFromBigDecimalSchemaForOas31() { final ModelConverterContextImpl context = getModelConverterContext(Json31.mapper(), true); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableBigDecimalModel.class)); io.swagger.v3.oas.models.media.Schema nullableBigDecimalField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableBigDecimalField"); assertNotNull(nullableBigDecimalField); assertTrue(isNullableInOAS31(nullableBigDecimalField)); assertNull(nullableBigDecimalField.getExample()); assertEquals(nullableBigDecimalField.getDefault(), 123); } @Test public void defaultValueShouldBeNullProvidedFromBooleanSchemaForOas31() { final ModelConverterContextImpl context = getModelConverterContext(Json31.mapper(), true); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableBooleanModel.class)); io.swagger.v3.oas.models.media.Schema nullableBooleanField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableBooleanField"); assertNotNull(nullableBooleanField); assertTrue(isNullableInOAS31(nullableBooleanField)); assertNull(nullableBooleanField.getExample()); assertNull(nullableBooleanField.getDefault()); } private static @NonNull ModelConverterContextImpl getModelConverterContext(ObjectMapper mapper, boolean openAPI31) { final ModelResolver modelResolver = new ModelResolver(mapper); Configuration configuration = new Configuration(); configuration.setOpenAPI31(openAPI31); modelResolver.setConfiguration(configuration); return new ModelConverterContextImpl(modelResolver); } private boolean isNullableInOAS31(io.swagger.v3.oas.models.media.Schema schema) { return schema.getTypes() != null && schema.getTypes().contains("null"); } public static class NullableStringModel { @Schema(nullable = true, defaultValue = "") private String nullableStringField; public String getNullableStringField() { return nullableStringField; } public void setNullableStringField(String nullableStringField) { this.nullableStringField = nullableStringField; } } public static class NullableIntegerModel { @Schema(nullable = true, defaultValue = "null") private Integer nullableIntegerField; public Integer getNullableIntegerField() { return nullableIntegerField; } public void setNullableIntegerField(Integer nullableIntegerField) { this.nullableIntegerField = nullableIntegerField; } } public static class NullableBigDecimalModel { @Schema(nullable = true, defaultValue = "123") private BigDecimal nullableBigDecimalField; public BigDecimal getNullableBigDecimalField() { return nullableBigDecimalField; } public void setNullableBigDecimalField(BigDecimal nullableBigDecimalField) { this.nullableBigDecimalField = nullableBigDecimalField; } } public static class NullableBooleanModel { @Schema(nullable = true) private Boolean nullableBooleanField; public Boolean getNullableBooleanField() { return nullableBooleanField; } public void setNullableBooleanField(Boolean nullableBooleanField) { this.nullableBooleanField = nullableBooleanField; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/issues/Issue5001Test.java ================================================ package io.swagger.v3.core.issues; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.oas.annotations.media.Schema; import org.testng.annotations.Test; import javax.annotation.Nullable; import java.util.Set; import static org.testng.Assert.*; /** * Reproduces GitHub Issue #5001 * Native support for @Nullable annotations to generate proper nullable types * * Tests that @Nullable annotation is recognized and generates appropriate nullable output: * - OAS 3.0: nullable keyword * - OAS 3.1: type array with "null" * * Note: This test uses javax.annotation.Nullable which is automatically transformed to * jakarta.annotation.Nullable in the swagger-core-jakarta module via the Eclipse Transformer. * * @see ... */ public class Issue5001Test { /** * Tests @Nullable annotation with OAS 3.1 (type array output) */ @Test public void testNullableWithOAS31() throws Exception { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); // Field with @Nullable should generate type array ["string", "null"] io.swagger.v3.oas.models.media.Schema nullableField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableString"); assertNotNull(nullableField, "nullableString property should exist"); assertNotNull(nullableField.getTypes(), "@Nullable should generate types array in OAS 3.1"); assertTrue(nullableField.getTypes().contains("string"), "types should include 'string'"); assertTrue(nullableField.getTypes().contains("null"), "types should include 'null'"); assertEquals(((Set) nullableField.getTypes()).size(), 2, "Should have exactly 2 types"); assertNull(nullableField.getNullable(), "OAS 3.1: @Nullable should NOT set nullable property - only use types array. " + "Setting nullable property is a spec violation in OpenAPI 3.1"); // Non-nullable field should only have string type io.swagger.v3.oas.models.media.Schema requiredField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("requiredString"); assertNotNull(requiredField); assertNotNull(requiredField.getTypes()); assertTrue(requiredField.getTypes().contains("string")); assertFalse(requiredField.getTypes().contains("null"), "Non-nullable field should not have 'null' type"); } /** * Tests @Nullable annotation with OAS 3.0 (nullable keyword output) */ @Test public void testNullableWithOAS30() throws Exception { final ModelResolver modelResolver = new ModelResolver(Json.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(false); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(NullableModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); // Field with @Nullable should set nullable=true in OAS 3.0 io.swagger.v3.oas.models.media.Schema nullableField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("nullableString"); assertNotNull(nullableField, "nullableString property should exist"); assertEquals(nullableField.getNullable(), Boolean.TRUE, "@Nullable should set nullable=true in OAS 3.0"); assertEquals(nullableField.getType(), "string", "type should be 'string'"); // Non-nullable field should not have nullable property io.swagger.v3.oas.models.media.Schema requiredField = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("requiredString"); assertNotNull(requiredField); assertNotEquals(requiredField.getNullable(), Boolean.TRUE, "Non-nullable field should not be nullable"); } /** * Tests explicit @Schema annotations with OAS 3.1 */ @Test public void testExplicitSchemaAnnotationsWithOAS31() throws Exception { final ModelResolver modelResolver = new ModelResolver(Json31.mapper()); Configuration configuration = new Configuration(); configuration.setOpenAPI31(true); modelResolver.setConfiguration(configuration); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final io.swagger.v3.oas.models.media.Schema model = context .resolve(new AnnotatedType(ExplicitSchemaModel.class)); assertNotNull(model); assertNotNull(model.getProperties()); // @Schema(nullable=true) should generate types array but not set nullable property in OAS 3.1 io.swagger.v3.oas.models.media.Schema explicitNullable = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("explicitNullableString"); assertNotNull(explicitNullable); assertTrue(explicitNullable.getTypes().contains("string")); assertTrue(explicitNullable.getTypes().contains("null")); assertNull(explicitNullable.getNullable(), "OAS 3.1 SPEC VIOLATION: @Schema(nullable=true) should NOT set nullable property - " + "only use types array. The nullable keyword doesn't exist in OpenAPI 3.1 spec"); // @Schema(types={"string", "null"}) should work io.swagger.v3.oas.models.media.Schema explicitTypes = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("explicitTypesString"); assertNotNull(explicitTypes); assertNotNull(explicitTypes.getTypes()); assertTrue(explicitTypes.getTypes().contains("string")); assertTrue(explicitTypes.getTypes().contains("null")); } /** * Model using @Nullable annotation * Note: Uses javax.annotation.Nullable which gets transformed to jakarta.annotation.Nullable * in the swagger-core-jakarta module */ public static class NullableModel { @Nullable private String nullableString; private String requiredString; public String getNullableString() { return nullableString; } public void setNullableString(String nullableString) { this.nullableString = nullableString; } public String getRequiredString() { return requiredString; } public void setRequiredString(String requiredString) { this.requiredString = requiredString; } } /** * Model using explicit @Schema annotations */ public static class ExplicitSchemaModel { @Schema(nullable = true) private String explicitNullableString; @Schema(types = {"string", "null"}) private String explicitTypesString; public String getExplicitNullableString() { return explicitNullableString; } public void setExplicitNullableString(String explicitNullableString) { this.explicitNullableString = explicitNullableString; } public String getExplicitTypesString() { return explicitTypesString; } public void setExplicitTypesString(String explicitTypesString) { this.explicitTypesString = explicitTypesString; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/matchers/SerializationMatchers.java ================================================ package io.swagger.v3.core.matchers; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.NumericNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Comparator; import static org.testng.Assert.assertEquals; public class SerializationMatchers { private static final Logger LOGGER = LoggerFactory.getLogger(SerializationMatchers.class); public static void assertEqualsToYaml(Object objectToSerialize, String yamlStr) { apply(objectToSerialize, yamlStr, Yaml.mapper()); } public static void assertEqualsToJson(Object objectToSerialize, String jsonStr) { apply(objectToSerialize, jsonStr, Json.mapper()); } public static void assertEqualsToYaml31(Object objectToSerialize, String yamlStr) { apply31(objectToSerialize, yamlStr, Yaml31.mapper()); } public static void assertEqualsToJson31(Object objectToSerialize, String jsonStr) { apply31(objectToSerialize, jsonStr, Json31.mapper()); } private static void apply(Object objectToSerialize, String str, ObjectMapper mapper) { final ObjectNode lhs = mapper.convertValue(objectToSerialize, ObjectNode.class); ObjectNode rhs = null; try { rhs = mapper.readValue(str, ObjectNode.class); } catch (IOException e) { LOGGER.error("Failed to read value", e); } if (!lhs.equals(new ObjectNodeComparator(), rhs)) { assertEquals(Yaml.pretty(lhs), Yaml.pretty(rhs)); } } private static void apply31(Object objectToSerialize, String str, ObjectMapper mapper) { final ObjectNode lhs = mapper.convertValue(objectToSerialize, ObjectNode.class); ObjectNode rhs = null; try { rhs = mapper.readValue(str, ObjectNode.class); } catch (IOException e) { LOGGER.error("Failed to read value", e); } if (!lhs.equals(new ObjectNodeComparator(), rhs)) { assertEquals(Yaml31.pretty(lhs), Yaml31.pretty(rhs)); } } static final class ObjectNodeComparator implements Comparator { @Override public int compare(JsonNode o1, JsonNode o2) { if (o1.equals(o2)) { return 0; } if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)) { double d1 = ((NumericNode) o1).asDouble(); double d2 = ((NumericNode) o2).asDouble(); return Double.compare(d1, d2); } int comp = o1.asText().compareTo(o2.asText()); if (comp == 0) { return Integer.compare(o1.hashCode(), o2.hashCode()); } return comp; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Address.java ================================================ package io.swagger.v3.core.oas.models; import javax.xml.bind.annotation.XmlElement; public class Address { private Integer streetNumber; @XmlElement(name = "streetNumber") public Integer getStreetNumber() { return streetNumber; } public void setStreetNumber(Integer streetNumber) { this.streetNumber = streetNumber; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ApiFirstRequiredFieldModel.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) @Schema(name = "aaa") public class ApiFirstRequiredFieldModel { @Schema(name = "bla", required = true) @XmlElement(name = "a") public String getA() { return "aaa"; } public String getC() { return "kkk"; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/BeanValidationsModel.java ================================================ package io.swagger.v3.core.oas.models; import javax.annotation.Nonnull; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Email; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import java.util.List; import java.util.Optional; public class BeanValidationsModel { @NotNull protected Long id; @Min(13) @Max(99) protected Integer age; @Pattern(regexp = "(?![-._])[-._a-zA-Z0-9]{3,32}") @Nonnull protected String username; @Size(min = 6, max = 20) protected String password; protected String passwordHint; @Email protected String email; @DecimalMin(value = "0.1", inclusive = false) protected Double minBalance; @DecimalMax(value = "1000000", inclusive = false) protected Double maxBalance; protected Integer birthYear; @Size(min = 2, max = 10) private List<@Size(min = 3, max = 4) String> items; private Optional<@Size(min= 1, max=10) String> optionalValue; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getPasswordHint() { return passwordHint; } public void setPasswordHint(String passwordHint) { this.passwordHint = passwordHint; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Double getMinBalance() { return minBalance; } public void setMinBalance(Double minBalance) { this.minBalance = minBalance; } public Double getMaxBalance() { return maxBalance; } public void setMaxBalance(Double maxBalance) { this.maxBalance = maxBalance; } public Integer getBirthYear() { return birthYear; } public void setBirthYear(Integer birthYear) { this.birthYear = birthYear; } public List getItems() { return items; } public void setItems(List items) { this.items = items; } public Optional getOptionalValue() { return optionalValue; } public void setOptionalValue(Optional optionalValue) { this.optionalValue = optionalValue; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Car.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; public class Car { @Schema(accessMode = Schema.AccessMode.READ_ONLY) public Integer getWheelCount() { return new Integer(4); } public void setWheelCount(Integer wheelCount) { // does nothing } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Cat.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.core.oas.models.composition.Pet; import io.swagger.v3.oas.annotations.media.Schema; @Schema public interface Cat extends Pet { Integer getClawCount(); void setClawCount(Integer name); } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Children.java ================================================ package io.swagger.v3.core.oas.models; public class Children { public String getName() { return null; } public void setName(String name) { } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ClientOptInput.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.models.OpenAPI; public class ClientOptInput { private String opts; private JsonNode model; private OpenAPI swagger; public String getOpts() { return opts; } public void setOpts(String opts) { this.opts = opts; } @Schema(hidden = true) public JsonNode getModel() { return model; } public void setModel(JsonNode model) { this.model = model; } @Schema(type = "Object") public OpenAPI getSwagger() { return swagger; } public void setSwagger(OpenAPI swagger) { this.swagger = swagger; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Department.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRootName; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.annotation.JsonTypeName; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "department") @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) @JsonRootName("department") @JsonTypeName("department") @JsonInclude(Include.NON_EMPTY) @JsonTypeInfo(include = As.WRAPPER_OBJECT, use = Id.NAME) @Schema(description = "Represents a Department in the system", title = "department") public class Department { private String name; private String deptCode; private Link parent; public Department() { } @XmlElement @JsonProperty @Schema(required = true) public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElement @JsonProperty @Schema(required = true) public String getDeptCode() { return deptCode; } public void setDeptCode(String deptCode) { this.deptCode = deptCode; } @JsonProperty("parentDepartment") @XmlElement(name = "parentDepartment") @Schema( type = "Link", required = true, description = "This department's parent. If this is a top-level department, the parent would be the enterprise.") public Link getParent() { return parent; } public void setParent(Link parent) { this.parent = parent; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Employee.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRootName; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.annotation.JsonTypeName; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import java.util.Set; @XmlRootElement(name = "employee") @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) @JsonRootName("employee") @JsonTypeName("employee") @JsonInclude(Include.NON_EMPTY) @JsonTypeInfo(include = As.WRAPPER_OBJECT, use = Id.NAME) @Schema(description = "Represents an Employee in the system", title = "employee") public class Employee { private int id; private String firstName; private String lastName; private Link dept; private Link manager; private Set> subordinates; public Employee() { // TODO Auto-generated constructor stub } @XmlElement @JsonProperty @Schema(description = "Note, this is server generated.", title = "Read-only") public int getId() { return id; } public void setId(int id) { this.id = id; } @XmlElement @JsonProperty @Schema(required = true) public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement @JsonProperty @Schema(required = true) public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @JsonProperty("department") @XmlElement(name = "department") @Schema(type = "Link", required = true, description = "The department this employee belongs to.") public Link getDept() { return dept; } public void setDept(Link dept) { this.dept = dept; } @JsonProperty("manager") @XmlElement(name = "manager") @Schema(type = "Link", required = true, description = "The employee this employee reports to.") public Link getManager() { return manager; } public void setManager(Link manager) { this.manager = manager; } @JsonProperty("team") @XmlElement(name = "team") @Schema(required = true, description = "List of employees that report to this employee.") public Set> getSubordinates() { return subordinates; } public void setSubordinates(Set> subordinates) { this.subordinates = subordinates; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/EmptyModel.java ================================================ package io.swagger.v3.core.oas.models; public class EmptyModel { } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Error.java ================================================ package io.swagger.v3.core.oas.models; public class Error { int code; String message; public Error() { } public Error(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/GuavaModel.java ================================================ package io.swagger.v3.core.oas.models; import com.google.common.base.Optional; public class GuavaModel { private Optional name; public Optional getName() { return name; } public void setName(Optional name) { this.name = name; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Issue534.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import java.util.List; public class Issue534 { public String name; @XmlElementWrapper(name = "order_specials") @XmlElement(name = "order_special") @Schema(hidden = true) public List getOrder_specials() { return null; } public void setOrder_specials(List items) { } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/JCovariantGetter.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; public abstract class JCovariantGetter { @Schema public Object getMyProperty() { return "42"; } @Schema public Object getMyOtherProperty() { return "42"; } public static class Sub extends JCovariantGetter { @Override public Integer getMyProperty() { return 42; } @Override public Integer getMyOtherProperty() { return 42; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/JacksonIntegerValueEnum.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.Hidden; /** * Enum holds values different from names. Schema model will derive Integer value from jackson annotation JsonValue on public method. */ public enum JacksonIntegerValueEnum { FIRST(2), SECOND(4), THIRD(6), @Hidden HIDDEN(-1); private final int value; JacksonIntegerValueEnum(int value) { this.value = value; } @JsonValue public Integer getValue() { return value; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/JacksonIntegerValueFieldEnum.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.Hidden; /** * Enum holds values different from names. Schema model will derive Integer value from jackson annotation JsonValue on private field. */ public enum JacksonIntegerValueFieldEnum { FIRST(2), SECOND(4), THIRD(6), @Hidden HIDDEN(-1); @JsonValue private final int value; JacksonIntegerValueFieldEnum(int value) { this.value = value; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/JacksonPropertyEnum.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.Hidden; public enum JacksonPropertyEnum { @JsonProperty("p1") PRIVATE, @JsonProperty("p2") PUBLIC, SYSTEM, INVITE_ONLY, @Hidden HIDDEN } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/JacksonReadonlyModel.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; public class JacksonReadonlyModel { @JsonProperty (access = JsonProperty.Access.READ_ONLY) public Integer getCount() { return null; } @JsonIgnore public void setCount(Integer count) { } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/JacksonValueEnum.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.Hidden; /** * Enum holds values different from names. Schema model will derive String value from jackson annotation JsonValue on public method. */ public enum JacksonValueEnum { FIRST("one"), SECOND("two"), THIRD("three"), @Hidden HIDDEN("hidden"); private final String value; JacksonValueEnum(String value) { this.value = value; } @JsonValue public String getValue() { return value; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/JacksonValueFieldEnum.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.Hidden; /** * Enum holds values different from names. Schema model will derive String value from jackson annotation JsonValue on private field. */ public enum JacksonValueFieldEnum { FIRST("one"), SECOND("two"), THIRD("three"), @Hidden HIDDEN("hidden"); @JsonValue private final String value; JacksonValueFieldEnum(String value) { this.value = value; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/JacksonValuePrivateEnum.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.Hidden; /** * Enum holds values different from names. Schema model will derive String value from jackson annotation JsonValue on private method. */ public enum JacksonValuePrivateEnum { FIRST("one"), SECOND("two"), THIRD("three"), @Hidden HIDDEN("hidden"); private final String value; JacksonValuePrivateEnum(String value) { this.value = value; } @JsonValue private String getValue() { return value; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/JodaDateTimeModel.java ================================================ package io.swagger.v3.core.oas.models; import org.joda.time.DateTime; public class JodaDateTimeModel { private DateTime createdAt; public DateTime getCreatedAt() { return createdAt; } public void setCreatedAt(DateTime createdAt) { this.createdAt = createdAt; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Link.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRootName; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.annotation.JsonTypeName; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "link") @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) @JsonRootName("link") @JsonTypeName("link") @JsonInclude(Include.NON_EMPTY) @JsonTypeInfo(include = As.WRAPPER_OBJECT, use = Id.NAME) @Schema(description = "Represents an association to another resource in the system", title = "link") public class Link { private String href; private String rel; private String status; public Link() { } @XmlElement @JsonProperty @Schema(required = true) public String getHref() { return href; } public void setHref(String href) { this.href = href; } @XmlElement @JsonProperty @Schema(required = true) public String getRel() { return rel; } public void setRel(String rel) { this.rel = rel; } @XmlElement @JsonProperty @Schema(required = true) public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Manufacturers.java ================================================ package io.swagger.v3.core.oas.models; import java.util.HashSet; public class Manufacturers { private HashSet countries; public HashSet getCountries() { return countries; } public void setCountries(HashSet countries) { this.countries = countries; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Model1155.java ================================================ package io.swagger.v3.core.oas.models; public class Model1155 { private boolean valid; private String value; public boolean is; public String get; public boolean isA; public String getA; public boolean isValid() { return valid; } public void setValid(boolean valid) { this.valid = valid; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } // jackson treats this as getter public boolean is_persistent() { return true; } // jackson treats this as getter public String gettersAndHaters() { return null; } // jackson doesn't treat this as getter boolean isometric() { return true; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Model1979.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; public class Model1979 { @Schema(nullable = true) public String id; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelExampleTest.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class ModelExampleTest { @Test(description = "it should create a model") public void createModel() { ObjectSchema model = new ObjectSchema(); model.addProperties("name", new StringSchema().example("Tony")); model.addProperties("id", new IntegerSchema().example(123)); assertNotNull(model); } @Test(description = "it should create a model with example") public void createModelWithExample() { ObjectSchema model = new ObjectSchema(); model.addProperties("name", new StringSchema().example("Tony")); model.addProperties("id", new IntegerSchema().example(123)); model.example("{\"name\":\"Fred\",\"id\":123456\"}"); assertEquals(model.getExample(), "{\"name\":\"Fred\",\"id\":123456\"}"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelPropertyName.java ================================================ package io.swagger.v3.core.oas.models; public class ModelPropertyName { public boolean is_persistent() { return true; } public String gettersAndHaters() { return null; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithAltPropertyName.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; @Schema(name = "sample_model") public class ModelWithAltPropertyName { protected int id; @Schema( name = "the_id", description = "Note, this is server generated.", title = "Read-only") public int getId() { return id; } public void setId(int id) { this.id = id; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithApiModel.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; @Schema(name = "MyModel") public class ModelWithApiModel { public String name; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithArrayOfSubclasses.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; import io.swagger.v3.oas.annotations.media.Schema; public class ModelWithArrayOfSubclasses { @Schema(description = "The holder") public class Holder extends SubB { } @Schema( discriminatorProperty = "name", discriminatorMapping = { @DiscriminatorMapping(schema = SubA.class, value = "a"), @DiscriminatorMapping(schema = SubB.class, value = "b") }, description = "Stuff" ) public class Base { private String name; public String getName() { return name; } } @Schema(description = "The SubA class") public class SubA extends Base { private Long count; public Long getCount() { return count; } } @Schema(description = "The SubB class") public class SubB extends Base { private String friend; private Base[] baseArray; public String getFriend() { return friend; } @ArraySchema( schema = @Schema(implementation = Base.class), arraySchema = @Schema( type = "array", description = "Thingy" ), minItems = 0, uniqueItems = true ) public Base[] getBaseArray() { return baseArray; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithBooleanProperty.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; public class ModelWithBooleanProperty { @Schema(allowableValues = "true") public Boolean isGreat; @Schema(allowableValues = {"1", "2"}) public Integer intValue; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithEnumArray.java ================================================ package io.swagger.v3.core.oas.models; import java.util.Set; public class ModelWithEnumArray { private Set actions; public Set getActions() { return actions; } public enum Action { CREATE, UPDATE, DELETE, COPY; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithEnumField.java ================================================ package io.swagger.v3.core.oas.models; public class ModelWithEnumField { public TestEnum enumValue; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithEnumProperty.java ================================================ package io.swagger.v3.core.oas.models; public class ModelWithEnumProperty { private TestEnum e; public TestEnum getEnumValue() { return e; } public void setEnumValue(TestEnum e) { this.e = e; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithEnumRefProperty.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; public class ModelWithEnumRefProperty { private TestEnum a; private TestEnum b; @Schema(enumAsRef = true) public TestSecondEnum c; public TestSecondEnum d; @Schema(enumAsRef = true) public TestEnum getA() { return a; } public void setA(TestEnum e) { this.a = a; } @Schema(enumAsRef = true) public TestEnum getB() { return b; } public void setB(TestEnum b) { this.b = b; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithFormattedStrings.java ================================================ package io.swagger.v3.core.oas.models; import java.net.URI; import java.net.URL; import java.util.Date; import java.util.UUID; public class ModelWithFormattedStrings { public UUID uuid; public URI uri; public URL url; public Date date; public byte aByte; public Byte aByteObject; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithJAXBAnnotations.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.annotation.JsonIgnore; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.util.List; @XmlRootElement(name = "rootName") public class ModelWithJAXBAnnotations { @XmlAttribute public String id; @XmlElement(name = "renamed") public String name; @JsonIgnore @XmlAttribute public String hidden; public List list; @XmlElementWrapper(name = "wrappedListItems") @XmlElement(name = "wrappedList") public List wrappedList; @XmlAttribute(name = "doNotUseMe") public List forcedElement; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithJacksonEnumField.java ================================================ package io.swagger.v3.core.oas.models; /** * Class of different enums for testing schema model */ public class ModelWithJacksonEnumField { public JacksonPropertyEnum firstEnumValue; public JacksonValueEnum secondEnumValue; public JacksonIntegerValueEnum thirdEnumValue; public JacksonValueFieldEnum fourthEnumValue; public JacksonIntegerValueFieldEnum fifthEnumValue; public JacksonValuePrivateEnum sixthEnumValue; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithJaxBDefaultValues.java ================================================ package io.swagger.v3.core.oas.models; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class ModelWithJaxBDefaultValues { @XmlElement(defaultValue = "Tony") public String name; @XmlElement(defaultValue = "100") public Integer age; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithModelPropertyOverrides.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; public class ModelWithModelPropertyOverrides { @ArraySchema(schema = @Schema(implementation = Children.class)) private String children; public String getChildren() { return children; } public void setChildren(String children) { this.children = children; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithNumbers.java ================================================ package io.swagger.v3.core.oas.models; import java.math.BigDecimal; import java.math.BigInteger; public class ModelWithNumbers { public short shortPrimitive; public Short shortObject; public int intPrimitive; public Integer intObject; public long longPrimitive; public Long longObject; public float floatPrimitive; public Float floatObject; public double doublePrimitive; public Double doubleObject; public BigInteger bigInteger; public BigDecimal bigDecimal; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithOffset.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; public class ModelWithOffset { public String id; @Schema(implementation = java.time.OffsetDateTime.class) public String offset; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithPrimitiveArray.java ================================================ package io.swagger.v3.core.oas.models; public class ModelWithPrimitiveArray { public int[] intArray; private long[] longArray; public long[] getLongArray() { return longArray; } public void setLongArray(long[] longArray) { this.longArray = longArray; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithRanges.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; public class ModelWithRanges { @Schema(description = "values with include range", minimum = "1", maximum = "5") public int getInclusiveRange() { return 2; } @Schema(description = "values with include range", minimum = "1", exclusiveMinimum = true, maximum = "5", exclusiveMaximum = true) public int getExclusiveRange() { return 2; } @Schema(description = "values with include range", minimum = "1") public int getPositiveInfinityRange() { return 2; } @Schema(description = "values with include range", maximum = "5") public int getNegativeInfinityRange() { return 2; } @Schema(description = "some string values", allowableValues = {"str1", "str2"}) public String getStringValues() { return "test"; } @Schema(description = "some string values", minimum = "1.0", maximum = "8.0", exclusiveMaximum = true) public Double getDoubleValues() { return 1.0; } @Schema(description = "some int values", allowableValues = {"1", "2"}) public int getIntAllowableValues() { return 2; } @Schema(description = "some int values with null", allowableValues = {"1", "2", "null"}) public int getIntAllowableValuesWithNull() { return 2; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ModelWithTuple2.java ================================================ package io.swagger.v3.core.oas.models; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.jackson.AbstractModelConverter; import io.swagger.v3.oas.models.media.MapSchema; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.text.WordUtils; import org.apache.commons.lang3.tuple.Pair; import java.util.Iterator; import java.util.Set; import static io.swagger.v3.core.util.RefUtils.constructRef; public class ModelWithTuple2 { @io.swagger.v3.oas.annotations.media.Schema(description = "Possible values for state property of timesheet or timesheet entry", required = true) public Pair timesheetStates; @io.swagger.v3.oas.annotations.media.Schema(description = "set of pairs", required = true) public Set> manyPairs; @io.swagger.v3.oas.annotations.media.Schema(description = "set of pairs with complex left", required = true) public Set> complexLeft; static class ComplexLeft { public String name; public Integer age; } public static class TupleAsMapModelConverter extends AbstractModelConverter { public TupleAsMapModelConverter(ObjectMapper mapper) { super(mapper); } @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { final JavaType javaType = _mapper.constructType(type.getType()); if (Pair.class.isAssignableFrom(javaType.getRawClass())) { final JavaType left = javaType.containedType(0); final String name = "MapOf" + WordUtils.capitalize(_typeName(left)); return new MapSchema() .name(name) .additionalProperties(context.resolve(new AnnotatedType(left))); } return super.resolve(type, context, chain); } } public static class TupleAsMapPropertyConverter extends AbstractModelConverter { public TupleAsMapPropertyConverter(ObjectMapper mapper) { super(mapper); } @Override public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator chain) { final JavaType javaType = _mapper.constructType(type.getType()); if (Pair.class.isAssignableFrom(javaType.getRawClass())) { if (!type.isSchemaProperty()) { return null; } final JavaType left = javaType.containedType(0); Schema schema = context.resolve(new AnnotatedType().type(left).schemaProperty(type.isSchemaProperty())); String pName = null; if (left != null) { BeanDescription valueTypeBeanDesc = _mapper.getSerializationConfig().introspect(left); pName = _typeName(left, valueTypeBeanDesc); } if ("object".equals(schema.getType()) && pName != null) { // create a reference for the items if (context.getDefinedModels().containsKey(pName)) { schema = new Schema().$ref(constructRef(pName)); } } else if (schema.get$ref() != null) { schema = new Schema().$ref(StringUtils.isNotEmpty(schema.get$ref()) ? schema.get$ref() : schema.getName()); } return new MapSchema().additionalProperties(schema); } if (chain.hasNext()) { return chain.next().resolve(type, context, chain); } return null; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/Person.java ================================================ package io.swagger.v3.core.oas.models; import java.util.Date; import java.util.Map; public class Person { private Long id; private String firstName; private Address address; private Map properties; private Date birthDate; private Float floatValue; private Double doubleValue; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Map getProperties() { return properties; } public void setProperties(Map properties) { this.properties = properties; } public Date getBirthDate() { return birthDate; } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } public Float getFloat() { return floatValue; } public void setFloat(Float floatValue) { this.floatValue = floatValue; } public Double getDouble() { return doubleValue; } public void setDouble(Double doubleValue) { this.doubleValue = doubleValue; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ReadOnlyFields.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; public class ReadOnlyFields { @Schema(accessMode = Schema.AccessMode.READ_ONLY) public Long id; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/ReadOnlyModel.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; public class ReadOnlyModel { private Integer id; private Integer readWriteId; @Schema(accessMode = Schema.AccessMode.READ_ONLY) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Schema(accessMode = Schema.AccessMode.READ_WRITE) public Integer getReadWriteId() { return readWriteId; } public void setReadWriteId(Integer readWriteId) { this.readWriteId = readWriteId; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/RequiredFields.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotNull; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import java.util.List; import java.util.Optional; public class RequiredFields { @Schema(description = "required", required = true) public Long required; @Schema(description = "not required") public Long notRequired; @Schema(description = "Optional field") public Optional optionalField; @Schema(description = "not required with annotation") @NotNull public Long notRequiredWithAnnotation; @Schema(description = "primitive type without constraint") public long primitiveTypeWithoutConstraint; @Schema(description = "primitive type with constraint") @NotNull public long primitiveTypeWithConstraint; @Schema(description = "mode auto", requiredMode = Schema.RequiredMode.AUTO) public Long modeAuto; @Schema(description = "mode auto with annotation", requiredMode = Schema.RequiredMode.AUTO) @NotNull public Long modeAutoWithAnnotation; @Schema(description = "mode required", requiredMode = Schema.RequiredMode.REQUIRED) public Long modeRequired; @Schema(description = "mode not required", requiredMode = Schema.RequiredMode.NOT_REQUIRED) public Long modeNotRequired; @Schema(description = "mode not required with annotation", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotNull public Long modeNotRequiredWithAnnotation; @Schema(description = "mode not required with annotation for NotBlank", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotBlank public String modeNotRequiredWithAnnotationForNotBlank; @Schema(description = "mode not required with annotation for NotEmpty", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotEmpty public List modeNotRequiredWithAnnotationForNotEmpty; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/RequiredRefFieldModel.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class RequiredRefFieldModel { @XmlElement(name = "a") @Schema(required = true) public String getA() { return "aaa"; } @XmlElement(name = "b") @Schema(required = true) public B getB() { return null; } static class B { public String foo; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/SpecialOrderItem.java ================================================ package io.swagger.v3.core.oas.models; public class SpecialOrderItem { public String name; public Long id; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/TestEnum.java ================================================ package io.swagger.v3.core.oas.models; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlType; @XmlType @XmlEnum(String.class) public enum TestEnum { @XmlEnumValue("PRIVATE") PRIVATE, @XmlEnumValue("PUBLIC") PUBLIC, @XmlEnumValue("SYSTEM") SYSTEM, @XmlEnumValue("INVITE_ONLY") INVITE_ONLY; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/TestSecondEnum.java ================================================ package io.swagger.v3.core.oas.models; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlType; @XmlType @XmlEnum(String.class) public enum TestSecondEnum { @XmlEnumValue("A_PRIVATE") A_PRIVATE, @XmlEnumValue("A_PUBLIC") A_PUBLIC, @XmlEnumValue("A_SYSTEM") A_SYSTEM, @XmlEnumValue("A_INVITE_ONLY") A_INVITE_ONLY; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/XmlFirstRequiredFieldModel.java ================================================ package io.swagger.v3.core.oas.models; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) @Schema(name = "aaa") public class XmlFirstRequiredFieldModel { @XmlElement(name = "a") @Schema(description = "bla", required = true) public String getA() { return "aaa"; } public String getC() { return "kkk"; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/AbstractBaseModelWithSubTypes.java ================================================ package io.swagger.v3.core.oas.models.composition; import com.fasterxml.jackson.annotation.JsonSubTypes; import io.swagger.v3.oas.annotations.media.Schema; @JsonSubTypes({@JsonSubTypes.Type(value = Thing1.class, name = "thing3"), @JsonSubTypes.Type(value = Thing2.class, name = "thing2")}) @Schema(description = "I am an Abstract Base Model with Sub-Types", discriminatorProperty = "_type") abstract public class AbstractBaseModelWithSubTypes { @Schema(description = "This value is used as a discriminator for serialization") public String _type; @Schema(description = "An arbitrary field") public String a; @Schema(description = "An arbitrary field") public String b; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/AbstractBaseModelWithoutFields.java ================================================ package io.swagger.v3.core.oas.models.composition; import com.fasterxml.jackson.annotation.JsonSubTypes; import io.swagger.v3.oas.annotations.media.Schema; @JsonSubTypes({@JsonSubTypes.Type(value = Thing3.class, name = "thing3")}) @Schema(description = "I am an Abstract Base Model without any declared fields and with Sub-Types") public abstract class AbstractBaseModelWithoutFields { } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/AbstractModelWithApiModel.java ================================================ package io.swagger.v3.core.oas.models.composition; import com.fasterxml.jackson.annotation.JsonSubTypes; import io.swagger.v3.oas.annotations.media.Schema; @Schema(name = "MyProperty") @JsonSubTypes({@JsonSubTypes.Type(value = ModelWithUrlProperty.class), @JsonSubTypes.Type(value = ModelWithValueProperty.class)}) public abstract class AbstractModelWithApiModel { private final String type; protected AbstractModelWithApiModel(String type) { this.type = type; } public String getType() { return type; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/Animal.java ================================================ package io.swagger.v3.core.oas.models.composition; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") @JsonSubTypes({ @Type(value = Human.class, name = "human"), @Type(value = Pet.class, name = "pet") }) public interface Animal { String getName(); void setName(String name); String getType(); void setType(String type); } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/AnimalClass.java ================================================ package io.swagger.v3.core.oas.models.composition; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") @JsonSubTypes({ @Type(value = HumanClass.class, name = "human"), @Type(value = PetClass.class, name = "pet") }) public class AnimalClass { String type; String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/AnimalWithSchemaSubtypes.java ================================================ package io.swagger.v3.core.oas.models.composition; import com.fasterxml.jackson.annotation.JsonTypeInfo; import io.swagger.v3.oas.annotations.media.Schema; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") @Schema(subTypes = {HumanWithSchemaSubtypes.class, PetWithSchemaSubtypes.class}) public class AnimalWithSchemaSubtypes { String type; String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/Human.java ================================================ package io.swagger.v3.core.oas.models.composition; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonPropertyOrder({"name", "type", "firstName", "lastName"}) public class Human implements Animal { private String name; private String type; private String firstName; private String lastName; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/HumanClass.java ================================================ package io.swagger.v3.core.oas.models.composition; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonPropertyOrder({"name", "type", "firstName", "lastName"}) public class HumanClass extends AnimalClass { private String name; private String type; private String firstName; private String lastName; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/HumanWithSchemaSubtypes.java ================================================ package io.swagger.v3.core.oas.models.composition; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonPropertyOrder({"name", "type", "firstName", "lastName"}) public class HumanWithSchemaSubtypes extends AnimalWithSchemaSubtypes { private String name; private String type; private String firstName; private String lastName; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/ModelWithFieldWithSubTypes.java ================================================ package io.swagger.v3.core.oas.models.composition; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "Class that has a field that is the AbstractBaseModelWithSubTypes") public class ModelWithFieldWithSubTypes { @Schema(description = "Contained field with sub-types") AbstractBaseModelWithSubTypes z; public AbstractBaseModelWithSubTypes getZ() { return z; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/ModelWithUrlProperty.java ================================================ package io.swagger.v3.core.oas.models.composition; import java.net.MalformedURLException; import java.net.URL; public class ModelWithUrlProperty extends AbstractModelWithApiModel { private final URL url; public ModelWithUrlProperty(String type, String url) { super(type); try { this.url = new URL(url); } catch (MalformedURLException e) { throw new IllegalArgumentException(e); } } public URL getUrl() { return url; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/ModelWithValueProperty.java ================================================ package io.swagger.v3.core.oas.models.composition; public class ModelWithValueProperty extends AbstractModelWithApiModel { private final String value; public ModelWithValueProperty(String type, String value) { super(type); this.value = value; } public String getValue() { return value; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/Pet.java ================================================ package io.swagger.v3.core.oas.models.composition; import io.swagger.v3.oas.annotations.media.Schema; public interface Pet extends Animal { @Schema(required = true, description = "The pet type") String getType(); void setType(String type); @Schema(required = true, description = "The name of the pet") String getName(); void setName(String name); @Schema(required = true) Boolean getIsDomestic(); void setIsDomestic(Boolean isDomestic); } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/PetClass.java ================================================ package io.swagger.v3.core.oas.models.composition; import io.swagger.v3.oas.annotations.media.Schema; public class PetClass extends AnimalClass { private String name; private String type; private Boolean isDomestic; @Schema(required = true, description = "The pet type") public String getType() { return type; } public void setType(String type) { this.type = type; } @Schema(required = true, description = "The name of the pet") public String getName() { return name; } public void setName(String name) { this.name = name; } @Schema(required = true) public Boolean getIsDomestic() { return isDomestic; } public void setIsDomestic(Boolean isDomestic) { this.isDomestic = isDomestic; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/PetWithSchemaSubtypes.java ================================================ package io.swagger.v3.core.oas.models.composition; import io.swagger.v3.oas.annotations.media.Schema; public class PetWithSchemaSubtypes extends AnimalWithSchemaSubtypes { private String name; private String type; private Boolean isDomestic; @Schema(required = true, description = "The pet type") public String getType() { return type; } public void setType(String type) { this.type = type; } @Schema(required = true, description = "The name of the pet") public String getName() { return name; } public void setName(String name) { this.name = name; } @Schema(required = true) public Boolean getIsDomestic() { return isDomestic; } public void setIsDomestic(Boolean isDomestic) { this.isDomestic = isDomestic; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/Thing1.java ================================================ package io.swagger.v3.core.oas.models.composition; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "Shake hands with Thing1", allOf = {AbstractBaseModelWithSubTypes.class}) public class Thing1 extends AbstractBaseModelWithSubTypes { @Schema(description = "Override the abstract a") public String a; @Schema(description = "Thing1 has an additional field") public int x; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/Thing2.java ================================================ package io.swagger.v3.core.oas.models.composition; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "and Thing2", allOf = {AbstractBaseModelWithSubTypes.class}) public class Thing2 extends AbstractBaseModelWithSubTypes { @Schema(description = "Override the abstract a") public String a; @Schema(description = "Thing2 has an additional field") public String s; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/composition/Thing3.java ================================================ package io.swagger.v3.core.oas.models.composition; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "Thing3", allOf = {AbstractBaseModelWithoutFields.class}) public class Thing3 extends AbstractBaseModelWithoutFields { @Schema(description = "Additional field a") String a; @Schema(description = "Additional field x") int x; public String getA() { return a; } public void setA(String a) { this.a = a; } public int getX() { return x; } public void setX(int x) { this.x = x; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/xmltest/NestedModelWithJAXBAnnotations.java ================================================ package io.swagger.v3.core.oas.models.xmltest; import com.fasterxml.jackson.annotation.JsonIgnore; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.util.List; @XmlRootElement(name = "RootName") public class NestedModelWithJAXBAnnotations { @XmlAttribute public String id; @XmlElement(name = "named") public String name; @XmlElement(name = "SubName") public SubModelWithJAXBAnnotations subName; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/xmltest/SubModelWithJAXBAnnotations.java ================================================ package io.swagger.v3.core.oas.models.xmltest; import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "SubType", propOrder = { "id", "name" }) public class SubModelWithJAXBAnnotations { @XmlAttribute public String id; @XmlElement public String name; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/oas/models/xmltest/package-info.java ================================================ @javax.xml.bind.annotation.XmlSchema( namespace = "https://www.openapis.org/test/nested", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED ) package io.swagger.v3.core.oas.models.xmltest; ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/ATMTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import static org.testng.Assert.assertNotNull; public class ATMTest extends SwaggerTestBase { @Test public void testATMModel() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(ATM.class)); assertNotNull(model); } public enum Currency {USA, CANADA} static class ATM { private Currency currency; public Currency getCurrency() { return currency; } public void setCurrency(Currency currency) { this.currency = currency; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AllofResolvingTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.annotations.media.Schema; import org.testng.annotations.Test; public class AllofResolvingTest extends SwaggerTestBase { @Test public void testAllofResolving() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(false).schemaResolution(io.swagger.v3.oas.models.media.Schema.SchemaResolution.ALL_OF); final ModelConverterContextImpl c = new ModelConverterContextImpl(modelResolver); // ModelConverters c = ModelConverters.getInstance(false, io.swagger.v3.oas.models.media.Schema.SchemaResolution.INLINE); c.resolve(new AnnotatedType(UserSchema.class)); String expectedYaml = "UserProperty:\n" + " type: object\n" + " description: Represents a user-specific property\n" + " example: User-specific example value\n" + "UserSchema:\n" + " type: object\n" + " properties:\n" + " propertyOne:\n" + " allOf:\n" + " - type: object\n" + " description: First user schema property\n" + " nullable: true\n" + " - $ref: \"#/components/schemas/UserProperty\"\n" + " propertyTwo:\n" + " allOf:\n" + " - type: object\n" + " description: Second user schema property\n" + " example: example value for propertyTwo\n" + " - $ref: \"#/components/schemas/UserProperty\"\n" + " propertyThree:\n" + " allOf:\n" + " - type: object\n" + " description: \"Third user schema property, with example for testing\"\n" + " example: example value for propertyThree\n" + " - $ref: \"#/components/schemas/UserProperty\"\n"; SerializationMatchers.assertEqualsToYaml(c.getDefinedModels(), expectedYaml); // stringSchemaMap = c.readAll(InlineSchemaSecond.class); c.resolve(new AnnotatedType(OrderSchema.class)); expectedYaml = "BasicProperty:\n" + " type: object\n" + " description: Represents a basic schema property\n" + "OrderProperty:\n" + " type: object\n" + " properties:\n" + " basicProperty:\n" + " $ref: \"#/components/schemas/BasicProperty\"\n" + " description: Represents an order-specific property\n" + " example: Order-specific example value\n" + "OrderSchema:\n" + " type: object\n" + " properties:\n" + " propertyOne:\n" + " allOf:\n" + " - type: object\n" + " description: First order schema property\n" + " nullable: true\n" + " - $ref: \"#/components/schemas/OrderProperty\"\n" + " userProperty:\n" + " allOf:\n" + " - type: object\n" + " description: \"Order schema property, references UserProperty\"\n" + " example: example value for userProperty\n" + " - $ref: \"#/components/schemas/UserProperty\"\n" + "UserProperty:\n" + " type: object\n" + " description: Represents a user-specific property\n" + " example: User-specific example value\n" + "UserSchema:\n" + " type: object\n" + " properties:\n" + " propertyOne:\n" + " allOf:\n" + " - type: object\n" + " description: First user schema property\n" + " nullable: true\n" + " - $ref: \"#/components/schemas/UserProperty\"\n" + " propertyTwo:\n" + " allOf:\n" + " - type: object\n" + " description: Second user schema property\n" + " example: example value for propertyTwo\n" + " - $ref: \"#/components/schemas/UserProperty\"\n" + " propertyThree:\n" + " allOf:\n" + " - type: object\n" + " description: \"Third user schema property, with example for testing\"\n" + " example: example value for propertyThree\n" + " - $ref: \"#/components/schemas/UserProperty\"\n"; SerializationMatchers.assertEqualsToYaml(c.getDefinedModels(), expectedYaml); } // Renamed class to better describe what it represents static class UserSchema { @Schema(description = "First user schema property", nullable = true) public UserProperty propertyOne; private UserProperty propertyTwo; @Schema(description = "Second user schema property", example = "example value for propertyTwo") public UserProperty getPropertyTwo() { return propertyTwo; } // Third property with no specific annotation. It's good to add some description or example for clarity @Schema(description = "Third user schema property, with example for testing", example = "example value for propertyThree") public UserProperty getPropertyThree() { return null; // returning null as per the test scenario } } // Renamed class to represent a different entity for the schema test static class OrderSchema { @Schema(description = "First order schema property", nullable = true) public OrderProperty propertyOne; private UserProperty userProperty; @Schema(description = "Order schema property, references UserProperty", example = "example value for userProperty") public UserProperty getUserProperty() { return userProperty; } } // Renamed properties to make them clearer about their role in the schema @Schema(description = "Represents a user-specific property", example = "User-specific example value") static class UserProperty { // public String value; } @Schema(description = "Represents an order-specific property", example = "Order-specific example value") static class OrderProperty { public BasicProperty basicProperty; } static class BasicSchema { @Schema(description = "First basic schema property") public BasicProperty propertyOne; private BasicProperty propertyTwo; @Schema(description = "Second basic schema property", example = "example value for propertyTwo") public BasicProperty getPropertyTwo() { return propertyTwo; } } // Renamed to represent a basic property common in various schemas @Schema(description = "Represents a basic schema property") static class BasicProperty { // public String value; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsExtensionsTest.java ================================================ package io.swagger.v3.core.resolving; import com.google.common.collect.ImmutableMap; import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.reflect.Method; import java.util.Collections; import java.util.Map; import static org.testng.Assert.assertEquals; public class AnnotationsUtilsExtensionsTest { @DataProvider private Object[][] expectedData() { return new Object[][]{ {"methodOne", Collections.emptyMap()}, {"methodTwo", Collections.emptyMap()}, {"methodThree", ImmutableMap.of( "x-test1", "value1", "x-test2", "value2", "x-test", ImmutableMap.of("test1", "value1", "test2", "value2"))}, {"methodFour", ImmutableMap.of( "x-test", ImmutableMap.of("test1", "value1", "test2", "value2"), "x-test1", "value1", "x-test2", "value2")}, {"methodFive", ImmutableMap.of( "x-test1", ImmutableMap.of("test1", "value1", "test2", "value2"), "x-test2", "value2")}, {"methodSix", ImmutableMap.of("x-test1", "value1", "x-test2", "value2")} }; } @Test(dataProvider = "expectedData") public void extensionsTest(String methodName, Map expected) throws NoSuchMethodException { final Method method = getClass().getDeclaredMethod(methodName); final Extension[] extensions = method.getAnnotation(Operation.class).extensions(); final Map map = AnnotationsUtils.getExtensions(extensions); assertEquals(map, expected); } @Operation(description = "method") private void methodOne() { } @Operation(description = "method", extensions = { @Extension(name = "test", properties = { @ExtensionProperty(name = "test1", value = "") })}) private void methodTwo() { } @Operation(description = "method", extensions = { @Extension(properties = { @ExtensionProperty(name = "test1", value = "value1"), @ExtensionProperty(name = "test2", value = "value2") }), @Extension(name = "test", properties = { @ExtensionProperty(name = "test1", value = "value1"), @ExtensionProperty(name = "test2", value = "value2") })}) private void methodThree() { } @Operation(description = "method", extensions = { @Extension(name = "test", properties = { @ExtensionProperty(name = "test1", value = "value1"), @ExtensionProperty(name = "test2", value = "value2") }), @Extension(properties = { @ExtensionProperty(name = "test1", value = "value1"), @ExtensionProperty(name = "test2", value = "value2") }) }) private void methodFour() { } @Operation(description = "method", extensions = { @Extension(properties = { @ExtensionProperty(name = "test1", value = "value1"), @ExtensionProperty(name = "test2", value = "value2") }), @Extension(name = "test1", properties = { @ExtensionProperty(name = "test1", value = "value1"), @ExtensionProperty(name = "test2", value = "value2") }) }) private void methodFive() { } @Operation(description = "method", extensions = { @Extension(name = "test1", properties = { @ExtensionProperty(name = "test1", value = "value1"), @ExtensionProperty(name = "test2", value = "value2") }), @Extension(properties = { @ExtensionProperty(name = "test1", value = "value1"), @ExtensionProperty(name = "test2", value = "value2") }) }) private void methodSix() { } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/AnnotationsUtilsHeadersTest.java ================================================ package io.swagger.v3.core.resolving; import com.google.common.collect.ImmutableMap; import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.models.headers.Header.StyleEnum; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Map; import java.util.Optional; import static org.testng.Assert.assertEquals; public class AnnotationsUtilsHeadersTest { private io.swagger.v3.oas.models.headers.Header header() { return new io.swagger.v3.oas.models.headers.Header().style(StyleEnum.SIMPLE); } @DataProvider private Object[][] expectedData() { return new Object[][]{ {"methodOne", Optional.empty()}, {"methodTwo", Optional.empty()}, {"methodThree", Optional.empty()}, {"methodFour", Optional.of(ImmutableMap.of( "", header().description("header"), "header1", header(), "header2", header().description("header 2"), "header3", header().$ref("#/components/schemas/header3") ))}, }; } @Test(dataProvider = "expectedData") public void extensionsTest(String methodName, Optional> expected) throws NoSuchMethodException { final Method method = getClass().getDeclaredMethod(methodName); final Header[] headers = Arrays.stream(method.getAnnotation(Operation.class).responses()) .flatMap(response -> Arrays.stream(response.headers())).toArray(Header[]::new); final Optional> optionalMap = AnnotationsUtils.getHeaders(headers, null, null); assertEquals(optionalMap, expected); } @Operation(description = "method") private void methodOne() { } @Operation(description = "method", responses = { @ApiResponse() }) private void methodTwo() { } @Operation(description = "method", responses = { @ApiResponse(headers = { @Header(name = "") }) }) private void methodThree() { } @Operation(description = "method", responses = { @ApiResponse(headers = { @Header(name = "", description = "header"), @Header(name = "header1"), @Header(name = "header2", description = "header 2"), @Header(name = "header3", ref = "#/components/schemas/header3") }) }) private void methodFour() { } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/BeanValidatorTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.oas.models.BeanValidationsModel; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.EmailSchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.NumberSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.math.BigDecimal; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class BeanValidatorTest { @Test(description = "read bean validations") public void readBeanValidatorTest() { final Map schemas = ModelConverters.getInstance().readAll(BeanValidationsModel.class); final Schema model = schemas.get("BeanValidationsModel"); final Map properties = model.getProperties(); assertTrue(model.getRequired().contains("id")); assertTrue(model.getRequired().contains("username")); final StringSchema username = (StringSchema) properties.get("username"); assertEquals((String) username.getPattern(), "(?![-._])[-._a-zA-Z0-9]{3,32}"); final IntegerSchema age = (IntegerSchema) properties.get("age"); assertEquals(age.getMinimum(), new BigDecimal(13.0)); assertEquals(age.getMaximum(), new BigDecimal(99.0)); final StringSchema password = (StringSchema) properties.get("password"); assertEquals((int) password.getMinLength(), 6); assertEquals((int) password.getMaxLength(), 20); final EmailSchema email = (EmailSchema) properties.get("email"); assertEquals((String) email.getFormat(), "email"); final NumberSchema minBalance = (NumberSchema) properties.get("minBalance"); assertTrue(minBalance.getExclusiveMinimum()); final NumberSchema maxBalance = (NumberSchema) properties.get("maxBalance"); assertTrue(maxBalance.getExclusiveMaximum()); final ArraySchema items = (ArraySchema) properties.get("items"); assertEquals((int) items.getMinItems(), 2); assertEquals((int) items.getMaxItems(), 10); assertEquals((int) items.getItems().getMinLength(), 3); assertEquals((int) items.getItems().getMaxLength(), 4); final StringSchema optionalValue = (StringSchema) properties.get("optionalValue"); assertEquals((int) optionalValue.getMinLength(), 1); assertEquals((int) optionalValue.getMaxLength(), 10); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/ComplexPropertyTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import static org.testng.Assert.assertNotNull; public class ComplexPropertyTest extends SwaggerTestBase { @Test public void testOuterBean() throws Exception { final ModelResolver modelResolver = modelResolver(); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(OuterBean.class)); assertNotNull(model); } static class OuterBean { public int counter; public InnerBean inner; } static class InnerBean { public int d; public int a; public int c; public int b; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/ComposedSchemaTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.resolving.resources.TestObject2616; import io.swagger.v3.core.resolving.resources.TestObjectTicket2620; import io.swagger.v3.core.resolving.resources.TestObjectTicket2620Subtypes; import io.swagger.v3.core.resolving.resources.TestObjectTicket2900; import io.swagger.v3.core.resolving.resources.TestObjectTicket4247; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class ComposedSchemaTest { @Test(description = "read composed schem refs #2620") public void readBilateralComposedSchema_ticket2620() { Map schemas = ModelConverters.getInstance().readAll(TestObjectTicket2620.class); Schema model = schemas.get("Child2TestObject"); Map properties = model.getProperties(); assertNotNull(properties.get("name")); assertNotNull(properties.get("childName")); assertFalse(model instanceof ComposedSchema); model = schemas.get("ChildTestObject"); properties = model.getProperties(); assertNotNull(properties.get("name")); assertNotNull(properties.get("childName")); assertFalse(model instanceof ComposedSchema); model = schemas.get("TestObjectTicket2620"); properties = model.getProperties(); assertNotNull(properties.get("name")); assertNull(properties.get("childName")); assertTrue(model instanceof ComposedSchema); assertEquals(((ComposedSchema) model).getOneOf().size(), 2); schemas = ModelConverters.getInstance().readAll(TestObjectTicket2620Subtypes.class); model = schemas.get("Child2TestObject"); assertNull(model.getProperties()); properties = ((ComposedSchema)model).getAllOf().get(1).getProperties(); assertNull(properties.get("name")); assertNotNull(properties.get("childName")); assertTrue(model instanceof ComposedSchema); model = schemas.get("ChildTestObject"); assertNull(model.getProperties()); properties = ((ComposedSchema)model).getAllOf().get(1).getProperties(); assertNull(properties.get("name")); assertNotNull(properties.get("childName")); assertTrue(model instanceof ComposedSchema); assertEquals(((ComposedSchema) model).getAllOf().size(), 2); model = schemas.get("TestObjectTicket2620Subtypes"); properties = model.getProperties(); assertNotNull(properties.get("name")); assertNull(properties.get("childName")); assertTrue(model instanceof ComposedSchema); assertEquals(((ComposedSchema) model).getOneOf().size(), 2); } @Test(description = "read composed schem refs #2900") public void readComposedSchema_ticket2900() { Json.mapper().addMixIn(TestObjectTicket2900.GsonJsonPrimitive.class, TestObjectTicket2900.GsonJsonPrimitiveMixIn.class); Map schemas = ModelConverters.getInstance().readAll(TestObjectTicket2900.class); Schema model = schemas.get("SomeDTO"); assertNotNull(model); Map properties = model.getProperties(); assertNotNull(properties.get("value")); assertEquals(properties.get("value").get$ref(), "#/components/schemas/MyJsonPrimitive"); assertEquals(properties.get("valueWithMixIn").get$ref(), "#/components/schemas/GsonJsonPrimitive"); model = schemas.get("MyJsonPrimitive"); assertNotNull(model); assertEquals(((ComposedSchema) model).getOneOf().size(), 2); assertEquals(((ComposedSchema)model).getOneOf().get(0).getType(), "string"); assertEquals(((ComposedSchema)model).getOneOf().get(1).getType(), "number"); model = schemas.get("GsonJsonPrimitive"); assertNotNull(model); assertEquals(((ComposedSchema) model).getOneOf().size(), 2); assertEquals(((ComposedSchema)model).getOneOf().get(0).getType(), "string"); assertEquals(((ComposedSchema)model).getOneOf().get(1).getType(), "number"); assertNull(model.getProperties()); } @Test(description = "read composed schem refs #2616") public void readArrayComposedSchema_ticket2616() { Map schemas = ModelConverters.getInstance().readAll(TestObject2616.class); Schema model = schemas.get("testObject"); assertNotNull(model); Map properties = model.getProperties(); assertNotNull(properties.get("objects")); assertTrue(properties.get("objects") instanceof ArraySchema); model = schemas.get("AbstractObject"); assertNotNull(model); assertTrue(model instanceof ComposedSchema); assertEquals(((ComposedSchema) model).getOneOf().size(), 2); model = schemas.get("AObject"); assertNotNull(model); model = schemas.get("BObject"); assertNotNull(model); model = schemas.get("objects"); assertNull(model); } @Test(description = "read single composed schem refs #2616") public void readComposedSchema_ticket2616() { Map schemas = ModelConverters.getInstance().readAll(TestObject2616.TestObject2616_Schema.class); Schema model = schemas.get("TestObject2616_Schema"); assertNotNull(model); Map properties = model.getProperties(); assertNotNull(properties.get("object")); assertEquals(properties.get("object").get$ref(), "#/components/schemas/AbstractObject"); model = schemas.get("AbstractObject"); assertNotNull(model); assertTrue(model instanceof ComposedSchema); assertEquals(((ComposedSchema) model).getOneOf().size(), 2); model = schemas.get("AObject"); assertNotNull(model); model = schemas.get("BObject"); assertNotNull(model); model = schemas.get("objects"); assertNull(model); } @Test(description = "read composed schem refs #4247") public void readComposedSchema_ticket4247() { Map schemas = ModelConverters.getInstance().readAll(TestObjectTicket4247.class); Schema model = schemas.get("TestObjectTicket4247"); assertNotNull(model); Map properties = model.getProperties(); assertNotNull(properties.get("value")); assertEquals(((ComposedSchema) properties.get("value")).getOneOf().size(), 2); assertEquals(((ComposedSchema)properties.get("value")).getOneOf().get(0).getType(), "string"); assertEquals(((ComposedSchema)properties.get("value")).getOneOf().get(1).getType(), "number"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/CompositionSuperfluousRefTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.Assert; import org.testng.annotations.Test; public class CompositionSuperfluousRefTest { static class SomeDto {} static class OtherDto {} static class MyDtoOneOf { @io.swagger.v3.oas.annotations.media.Schema(oneOf = { SomeDto.class, OtherDto.class }) public Object myProperty; } static class MyDtoWithAnyOf { @io.swagger.v3.oas.annotations.media.Schema(anyOf = { SomeDto.class, OtherDto.class }) public Object myProperty; } static class MyDtoWithAllOf { @io.swagger.v3.oas.annotations.media.Schema(allOf = { SomeDto.class, OtherDto.class }) public Object myProperty; } static class MyDtoWithoutComposition { @io.swagger.v3.oas.annotations.media.Schema(implementation = SomeDto.class) public Object myProperty; } static class MyDtoWithNonMatchingRef { @io.swagger.v3.oas.annotations.media.Schema( ref = "#/components/schemas/ThirdDto", oneOf = { SomeDto.class, OtherDto.class } ) public Object myProperty; } @Test public void oneOf_shouldNotHaveRef() { ResolvedSchema rs = ModelConverters.getInstance(false) .resolveAsResolvedSchema(new AnnotatedType(MyDtoOneOf.class)); Schema prop = (Schema) rs.schema.getProperties().get("myProperty"); Assert.assertNull(prop.get$ref()); Assert.assertNotNull(prop.getOneOf()); Assert.assertEquals(prop.getOneOf().size(), 2); } @Test public void anyOf_shouldNotHaveRef() { ResolvedSchema rs = ModelConverters.getInstance(false) .resolveAsResolvedSchema(new AnnotatedType(MyDtoWithAnyOf.class)); Schema prop = (Schema) rs.schema.getProperties().get("myProperty"); Assert.assertNull(prop.get$ref()); Assert.assertNotNull(prop.getAnyOf()); Assert.assertEquals(prop.getAnyOf().size(), 2); } @Test public void allOf_shouldNotHaveRef() { ResolvedSchema rs = ModelConverters.getInstance(false) .resolveAsResolvedSchema(new AnnotatedType(MyDtoWithAllOf.class)); Schema prop = (Schema) rs.schema.getProperties().get("myProperty"); Assert.assertNull(prop.get$ref()); Assert.assertNotNull(prop.getAllOf()); Assert.assertEquals(prop.getAllOf().size(), 2); } @Test public void testNonMatchingRef_shouldPreserveRef() { ResolvedSchema rs = ModelConverters.getInstance(false) .resolveAsResolvedSchema(new AnnotatedType(MyDtoWithNonMatchingRef.class)); Schema prop = (Schema) rs.schema.getProperties().get("myProperty"); Assert.assertNotNull(prop.get$ref()); Assert.assertEquals(prop.get$ref(), "#/components/schemas/ThirdDto"); //In 3.x refs cannot have siblings Assert.assertNull(prop.getOneOf()); } @Test public void oneOf_shouldNotHaveRef31() { ResolvedSchema rs = ModelConverters.getInstance(true) .resolveAsResolvedSchema(new AnnotatedType(MyDtoOneOf.class)); Schema prop = (Schema) rs.schema.getProperties().get("myProperty"); Assert.assertNull(prop.get$ref()); Assert.assertNotNull(prop.getOneOf()); Assert.assertEquals(prop.getOneOf().size(), 2); } @Test public void anyOf_shouldNotHaveRef31() { ResolvedSchema rs = ModelConverters.getInstance(true) .resolveAsResolvedSchema(new AnnotatedType(MyDtoWithAnyOf.class)); Schema prop = (Schema) rs.schema.getProperties().get("myProperty"); Assert.assertNull(prop.get$ref()); Assert.assertNotNull(prop.getAnyOf()); Assert.assertEquals(prop.getAnyOf().size(), 2); } @Test public void allOf_shouldNotHaveRef31() { ResolvedSchema rs = ModelConverters.getInstance(true) .resolveAsResolvedSchema(new AnnotatedType(MyDtoWithAllOf.class)); Schema prop = (Schema) rs.schema.getProperties().get("myProperty"); Assert.assertNull(prop.get$ref()); Assert.assertNotNull(prop.getAllOf()); Assert.assertEquals(prop.getAllOf().size(), 2); } @Test public void testNonMatchingRef_shouldPreserveRef31() { ResolvedSchema rs = ModelConverters.getInstance(true) .resolveAsResolvedSchema(new AnnotatedType(MyDtoWithNonMatchingRef.class)); Schema prop = (Schema) rs.schema.getProperties().get("myProperty"); Assert.assertNotNull(prop.get$ref()); Assert.assertEquals(prop.get$ref(), "#/components/schemas/ThirdDto"); Assert.assertNotNull(prop.getOneOf()); Assert.assertEquals(prop.getOneOf().size(), 2); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/ContainerTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.resolving.resources.InnerType; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class ContainerTest extends SwaggerTestBase { @Test public void testArray() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(ArrayBean.class)); final Map props = model.getProperties(); assertEquals(1, props.size()); final Schema prop = props.get("a"); assertNotNull(prop); assertEquals(prop.getType(), "array"); final Schema items = ((ArraySchema) prop).getItems(); assertNotNull(items); assertEquals(items.getType(), "integer"); } @Test public void testMap() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(MapBean.class)); final Map props = model.getProperties(); assertEquals(1, props.size()); final Schema prop = props.get("stuff"); assertNotNull(prop); assertEquals(prop.getType(), "object"); final Schema items = (Schema)prop.getAdditionalProperties(); assertNotNull(items); assertEquals(items.getType(), "string"); assertEquals(items.getFormat(), "date-time"); } @Test public void testComplexMap() throws Exception { ModelResolver resolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(resolver); context.resolve(new AnnotatedType(WrapperType.class)); final Map models = context.getDefinedModels(); final Schema innerType = models.get("InnerType"); assertNotNull(innerType); final Map innerProps = innerType.getProperties(); assertEquals(innerProps.size(), 2); final Schema foo = innerProps.get("foo"); assertEquals(foo.getType(), "integer"); assertEquals(foo.getFormat(), "int32"); final Schema name = innerProps.get("name"); assertEquals(name.getType(), "string"); final Schema wrapperType = models.get("WrapperType"); assertNotNull(wrapperType); assertEquals(((Schema) wrapperType.getProperties().get("innerType")).getType(), "object"); } static class ArrayBean { public int[] a; } static class MapBean { public Map stuff; } static class WrapperType { public Map innerType; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/EnumTest.java ================================================ package io.swagger.v3.core.resolving; import com.google.common.base.Functions; import com.google.common.collect.Collections2; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.util.*; import java.util.stream.Collectors; import static org.testng.Assert.*; import static org.testng.AssertJUnit.assertFalse; public class EnumTest extends SwaggerTestBase { @Test public void testEnum() { final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context.resolve((new AnnotatedType().type(Currency.class))); assertNotNull(model); assertTrue(model instanceof StringSchema); final StringSchema strModel = (StringSchema) model; assertNotNull(strModel.getEnum()); final Collection modelValues = new ArrayList(Collections2.transform(Arrays.asList(Currency.values()), Functions.toStringFunction())); assertEquals(strModel.getEnum(), modelValues); final Schema property = context.resolve(new AnnotatedType().type(Currency.class).schemaProperty(true)); assertNotNull(property); assertTrue(property instanceof StringSchema); final StringSchema strProperty = (StringSchema) property; assertNotNull(strProperty.getEnum()); final Collection values = new ArrayList<>(Collections2.transform(Arrays.asList(Currency.values()), Functions.toStringFunction())); assertEquals(strProperty.getEnum(), values); } @Test public void testEnumGenerics() { final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context.resolve((new AnnotatedType().type(Contract.class))); assertBasicModelStructure(model, "Contract"); assertPropertyExists(model, "type"); } @Test public void testEnumPropertyWithSchemaAnnotation() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context.resolve(new AnnotatedType().type(ClassWithEnumAsRefProperty.class)); assertBasicModelStructure(model, "ClassWithEnumAsRefProperty"); assertPropertyExists(model, "enumWithSchemaProperty"); final Schema enumPropertySchema = (Schema) model.getProperties().get("enumWithSchemaProperty"); assertEnumAsRefProperty(enumPropertySchema, "#/components/schemas/EnumWithSchemaProperty"); assertEquals(enumPropertySchema.getDescription(), "Property description"); } @Test public void testEnumPropertyWithGlobalSwitchOnlyOpenApi31() { ModelResolver.enumsAsRef = true; final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context.resolve(new AnnotatedType().type(ClassWithPlainEnum.class)); assertBasicModelStructure(model, "ClassWithPlainEnum"); assertPropertyExists(model, "plainEnum"); final Schema enumPropertySchema = (Schema) model.getProperties().get("plainEnum"); assertNotNull(enumPropertySchema.get$ref()); assertNull(enumPropertySchema.getEnum()); assertEquals(enumPropertySchema.getDescription(), "Plain enum property"); assertEnumComponentExists(context, ClassWithPlainEnum.PlainEnum.values(), null); // Reset the static field ModelResolver.enumsAsRef = false; } @Test public void testArrayOfEnumWithSchemaAnnotationOpenApi31() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context.resolve(new AnnotatedType().type(ClassWithEnumArray.class)); assertBasicModelStructure(model, "ClassWithEnumArray"); assertPropertyExists(model, "enumArray"); final Schema arrayPropertySchema = (Schema) model.getProperties().get("enumArray"); assertArrayWithEnumRef(arrayPropertySchema); assertEnumComponentExists(context, ClassWithEnumArray.ArrayEnum.values(), "Enum description"); } @Test public void testArrayOfEnumWithSchemaAnnotationOpenApi30() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(false); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context.resolve(new AnnotatedType().type(ClassWithEnumArray.class)); assertBasicModelStructure(model, "ClassWithEnumArray"); assertPropertyExists(model, "enumArray"); final Schema arrayPropertySchema = (Schema) model.getProperties().get("enumArray"); assertArrayWithEnumRef(arrayPropertySchema); assertEnumComponentExists(context, ClassWithEnumArray.ArrayEnum.values(), "Enum description"); } @Test public void testControlTestNoRefOpenApi31() { ModelResolver.enumsAsRef = false; final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context.resolve(new AnnotatedType().type(ClassWithPlainEnum.class)); assertBasicModelStructure(model, "ClassWithPlainEnum"); assertPropertyExists(model, "plainEnum"); final Schema enumPropertySchema = (Schema) model.getProperties().get("plainEnum"); assertInlineEnumProperty(enumPropertySchema); // Apply broad assertions - verify no components are created for inline enums Map components = context.getDefinedModels(); if (components != null && !components.isEmpty()) { Set expected = Arrays.stream(ClassWithPlainEnum.PlainEnum.values()) .map(Enum::name) .collect(Collectors.toSet()); Schema enumComponent = findEnumComponent(components, expected); assertNull(enumComponent, "No enum component should exist for inline enums"); } } @Test public void testControlTestNoRefOpenApi30() { ModelResolver.enumsAsRef = false; final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(false); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context.resolve(new AnnotatedType().type(ClassWithPlainEnum.class)); assertBasicModelStructure(model, "ClassWithPlainEnum"); assertPropertyExists(model, "plainEnum"); final Schema enumPropertySchema = (Schema) model.getProperties().get("plainEnum"); assertInlineEnumProperty(enumPropertySchema); // Apply broad assertions - verify no components are created for inline enums Map components = context.getDefinedModels(); if (components != null && !components.isEmpty()) { Set expected = Arrays.stream(ClassWithPlainEnum.PlainEnum.values()) .map(Enum::name) .collect(Collectors.toSet()); Schema enumComponent = findEnumComponent(components, expected); assertNull(enumComponent, "No enum component should exist for inline enums"); } } @Test public void testEnumWithAllOfSchemaResolutionOpenApi30() { final ModelResolver modelResolver = new ModelResolver(mapper()) .openapi31(false) .schemaResolution(Schema.SchemaResolution.ALL_OF); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context.resolve(new AnnotatedType().type(ClassWithEnumAsRefProperty.class)); assertBasicModelStructure(model, "ClassWithEnumAsRefProperty"); assertPropertyExists(model, "enumWithSchemaProperty"); final Schema enumPropertySchema = (Schema) model.getProperties().get("enumWithSchemaProperty"); boolean hasEnumRef = false; for (Object allOfItem : enumPropertySchema.getAllOf()) { if (allOfItem instanceof Schema) { Schema allOfSchema = (Schema) allOfItem; if ("#/components/schemas/EnumWithSchemaProperty".equals(allOfSchema.get$ref())) { hasEnumRef = true; break; } } } assertTrue(hasEnumRef, "AllOf should contain reference to enum component"); assertEnumComponentExists(context, ClassWithEnumAsRefProperty.EnumWithSchemaProperty.values(), "Enum description"); } private void assertBasicModelStructure(Schema model, String expectedName) { assertNotNull(model); assertEquals(model.getName(), expectedName); } private void assertPropertyExists(Schema model, String propertyName) { assertTrue(model.getProperties().containsKey(propertyName)); assertNotNull(model.getProperties().get(propertyName)); } private void assertEnumComponentExists(ModelConverterContextImpl context, Enum[] enumValues, String expectedDescription) { Map components = context.getDefinedModels(); assertNotNull(components); assertFalse(components.isEmpty()); Set expected = Arrays.stream(enumValues) .map(Enum::name) .collect(Collectors.toCollection(LinkedHashSet::new)); Schema enumComponent = findEnumComponent(components, expected); assertNotNull(enumComponent); assertEquals(enumComponent.getDescription(), expectedDescription); } private void assertEnumComponentExistsWithDefault(ModelConverterContextImpl context, Enum[] enumValues, String expectedDescription, String expectedDefault) { assertEnumComponentExists(context, enumValues, expectedDescription); Map components = context.getDefinedModels(); Set expected = Arrays.stream(enumValues) .map(Enum::name) .collect(Collectors.toCollection(LinkedHashSet::new)); Schema enumComponent = findEnumComponent(components, expected); assertEquals(enumComponent.getDefault(), expectedDefault); } private Schema findEnumComponent(Map components, Set expectedValues) { return components.values().stream() .filter(Objects::nonNull) .filter(s -> s.getEnum() != null) .filter(s -> { List ev = s.getEnum(); Set vals = ev.stream().map(Object::toString).collect(Collectors.toSet()); return vals.containsAll(expectedValues) && expectedValues.containsAll(vals); }) .findFirst() .orElse(null); } private void assertEnumAsRefProperty(Schema propertySchema, String expectedRef) { assertEquals(propertySchema.get$ref(), expectedRef); assertNull(propertySchema.getEnum()); } private void assertInlineEnumProperty(Schema propertySchema) { assertNotNull(propertySchema.getEnum()); assertNull(propertySchema.get$ref()); } private void assertArrayWithEnumRef(Schema arrayPropertySchema) { assertNotNull(arrayPropertySchema.getItems()); assertNotNull(arrayPropertySchema.getItems().get$ref()); } public static class ClassWithEnumAsRefProperty { @io.swagger.v3.oas.annotations.media.Schema(enumAsRef = true, description = "Property description", maximum = "1923234") public final EnumWithSchemaProperty enumWithSchemaProperty; public ClassWithEnumAsRefProperty(EnumWithSchemaProperty enumWithSchemaProperty) { this.enumWithSchemaProperty = enumWithSchemaProperty; } @io.swagger.v3.oas.annotations.media.Schema(description = "Enum description") public enum EnumWithSchemaProperty { VALUE1, VALUE2 } } public static class ClassWithEnumArray { @io.swagger.v3.oas.annotations.media.ArraySchema(schema = @io.swagger.v3.oas.annotations.media.Schema(enumAsRef = true, description = "Property Description")) public final ArrayEnum[] enumArray; public ClassWithEnumArray(ArrayEnum[] enumArray) { this.enumArray = enumArray; } @io.swagger.v3.oas.annotations.media.Schema(description = "Enum description") public enum ArrayEnum { FIRST, SECOND, THIRD } } public static class ClassWithPlainEnum { @io.swagger.v3.oas.annotations.media.Schema(description = "Plain enum property") public final PlainEnum plainEnum; public ClassWithPlainEnum(PlainEnum plainEnum) { this.plainEnum = plainEnum; } public enum PlainEnum { ONE, TWO, THREE } } public enum Currency { USA, CANADA } public static class Contract { private Enum type; public Enum getType() { return type; } public Contract setType(Enum type) { this.type = type; return this; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/HiddenFieldTest.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class HiddenFieldTest { @Test(description = "it should ignore a hidden field") public void testHiddenField() { final Map models = ModelConverters.getInstance().read(ModelWithHiddenFields.class); final Schema model = models.get("ModelWithHiddenFields"); assertNotNull(model); assertEquals(model.getProperties().size(), 2); final Schema idValue = (Schema) model.getProperties().get("id"); assertTrue(idValue instanceof IntegerSchema); assertTrue(model.getRequired().contains("id")); final Schema nameValue = (Schema) model.getProperties().get("name"); assertTrue(nameValue instanceof StringSchema); final Schema passwordValue = (Schema) model.getProperties().get("password"); assertNull(passwordValue); } static class ModelWithHiddenFields { @io.swagger.v3.oas.annotations.media.Schema(required = true) public Long id = null; @io.swagger.v3.oas.annotations.media.Schema(required = true, hidden = false) public String name = null; @io.swagger.v3.oas.annotations.media.Schema(hidden = true) public String password = null; } @Test(description = "it should ignore a hidden field in @JsonCreator") public void testHiddenFieldInJsonCreator() { final Map models = ModelConverters.getInstance().read(ModelWithHiddenFieldsInJsonCreator.class); final Schema model = models.get("ModelWithHiddenFieldsInJsonCreator"); assertNotNull(model); assertEquals(model.getProperties().size(), 1); final Schema idValue = (Schema) model.getProperties().get("id"); assertTrue(idValue instanceof IntegerSchema); final Schema hiddenValue = (Schema) model.getProperties().get("hidden"); assertNull(hiddenValue); } static class ModelWithHiddenFieldsInJsonCreator { @JsonProperty("id") private final Long id; @io.swagger.v3.oas.annotations.media.Schema(hidden = true) @JsonProperty("hidden") private final String hidden; @JsonCreator public ModelWithHiddenFieldsInJsonCreator(@JsonProperty("id") Long id, @JsonProperty("hidden") @io.swagger.v3.oas.annotations.media.Schema(hidden = true) String hidden) { this.id = id; this.hidden = hidden; } public Long getId() { return id; } @io.swagger.v3.oas.annotations.media.Schema(hidden = true) public String getHidden() { return hidden; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/InheritedBeanTest.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class InheritedBeanTest extends SwaggerTestBase { private ModelResolver modelResolver; private ModelConverterContextImpl context; @BeforeMethod public void setup() { ModelResolver.composedModelPropertiesAsSibling = false; modelResolver = new ModelResolver(new ObjectMapper()); context = new ModelConverterContextImpl(modelResolver); } @AfterTest public void afterTest() { ModelResolver.composedModelPropertiesAsSibling = false; } @Test public void testInheritedBean() throws Exception { final Schema baseModel = context.resolve(new AnnotatedType(BaseBean.class)); assertNotNull(baseModel); assertBasePropertiesValid(baseModel.getProperties()); assertEquals(baseModel.getDiscriminator().getPropertyName(), "type"); assertEquals(baseModel.getDiscriminator().getMapping().get("Sub1BeanMapped"), "#/components/schemas/Sub1Bean"); final Schema subModel = context.getDefinedModels().get("Sub1Bean"); assertNotNull(subModel); // make sure child points at parent assertTrue(subModel instanceof ComposedSchema); ComposedSchema cm = (ComposedSchema) subModel; assertEquals(cm.getAllOf().get(0).get$ref(), "#/components/schemas/BaseBean"); // make sure parent properties are filtered out of subclass assertSub1PropertiesValid(cm.getAllOf().get(1).getProperties()); } @Test public void testInheritedChildBean() throws Exception { final Schema subModel = context.resolve(new AnnotatedType(Sub1Bean.class)); assertNotNull(subModel); // make sure child points at parent assertTrue(subModel instanceof ComposedSchema); ComposedSchema cm = (ComposedSchema) subModel; assertEquals(cm.getAllOf().get(0).get$ref(), "#/components/schemas/BaseBean"); // make sure parent properties are filtered out of subclass assertSub1PropertiesValid(cm.getAllOf().get(1).getProperties()); final Schema baseModel = context.getDefinedModels().get("BaseBean"); assertNotNull(baseModel); assertBasePropertiesValid(baseModel.getProperties()); } @Test public void testComposedChildBean() throws Exception { final Schema subModel = context.resolve(new AnnotatedType(Sub2Bean.class)); assertNotNull(subModel); // make sure child points at parent assertTrue(subModel instanceof ComposedSchema); ComposedSchema cm = (ComposedSchema) subModel; assertEquals(cm.getAllOf().get(0).get$ref(), "#/components/schemas/BaseBean2"); // make sure parent properties are filtered out of subclass assertSub1PropertiesValid(cm.getAllOf().get(1).getProperties()); final Schema baseModel = context.getDefinedModels().get("BaseBean2"); assertNotNull(baseModel); assertBase2PropertiesValid(baseModel.getProperties()); } @Test public void testComposedUberObject() throws Exception { final Schema uberModel = context.resolve(new AnnotatedType(UberObject.class)); assertNotNull(uberModel); // make sure child points at parent assertTrue(uberModel instanceof ComposedSchema); ComposedSchema cm = (ComposedSchema) uberModel; assertEquals(cm.getAnyOf().size(), 2); assertEquals(cm.getAnyOf().get(0).get$ref(), "#/components/schemas/UserObject"); // parent properties are filtered out of subclass when parent doesn't define subtypes assertNotNull(cm.getProperties()); assertEquals(cm.getProperties().size(), 3); final Schema interfaceModel = context.getDefinedModels().get("UserObject"); assertNotNull(interfaceModel); assertUserObjectPropertiesValid(interfaceModel.getProperties()); } @Test public void testHierarchy() throws Exception { final Schema baseModel = context.resolve(new AnnotatedType(BaseBean3.class)); assertNotNull(baseModel); assertBasePropertiesValid(baseModel.getProperties()); assertEquals(baseModel.getDiscriminator().getPropertyName(), "type"); assertEquals(baseModel.getDiscriminator().getMapping().get("ChildBean3Mapped"), "#/components/schemas/ChildBean3"); final Schema subModel = context.getDefinedModels().get("ChildBean3"); assertNotNull(subModel); // make sure child points at parent assertTrue(subModel instanceof ComposedSchema); ComposedSchema cm = (ComposedSchema) subModel; assertEquals(cm.getAllOf().get(0).get$ref(), "#/components/schemas/BaseBean3"); // make sure parent properties are filtered out of subclass assertSub1PropertiesValid(cm.getAllOf().get(1).getProperties()); // assert grandchild final Schema subSubModel = context.getDefinedModels().get("GrandChildBean3"); assertNotNull(subSubModel); // make sure child points at parent assertTrue(subSubModel instanceof ComposedSchema); cm = (ComposedSchema) subSubModel; assertEquals(cm.getAllOf().get(0).get$ref(), "#/components/schemas/ChildBean3"); // make sure parent properties are filtered out of subclass assertSub2PropertiesValid(cm.getAllOf().get(1).getProperties()); } private void assertBasePropertiesValid(Map baseProperites) { assertEquals(baseProperites.size(), 3); for (Map.Entry entry : baseProperites.entrySet()) { final String name = entry.getKey(); final Schema prop = entry.getValue(); if ("type".equals(name)) { assertEquals(prop.getType(), "string"); } else if ("a".equals(name)) { assertEquals(prop.getType(), "integer"); assertEquals(prop.getFormat(), "int32"); } else if ("b".equals(name)) { assertEquals(prop.getType(), "string"); } } } private void assertBase2PropertiesValid(Map baseProperites) { assertEquals(baseProperites.size(), 4); for (Map.Entry entry : baseProperites.entrySet()) { final String name = entry.getKey(); final Schema prop = entry.getValue(); if ("type".equals(name)) { assertEquals(prop.getType(), "string"); } else if ("a".equals(name)) { assertEquals(prop.getType(), "integer"); assertEquals(prop.getFormat(), "int32"); } else if ("b".equals(name)) { assertEquals(prop.getType(), "string"); } else if ("d".equals(name)) { assertEquals(prop.getType(), "integer"); assertEquals(prop.getFormat(), "int32"); } } } private void assertSub1PropertiesValid(Map subProperties) { assertEquals(subProperties.size(), 1); for (Map.Entry entry : subProperties.entrySet()) { final String name = entry.getKey(); final Schema prop = entry.getValue(); if ("c".equals(name)) { assertEquals(prop.getType(), "integer"); assertEquals(prop.getFormat(), "int32"); } } } private void assertUserObjectPropertiesValid(Map subProperties) { assertEquals(subProperties.size(), 2); for (Map.Entry entry : subProperties.entrySet()) { final String name = entry.getKey(); final Schema prop = entry.getValue(); if ("id".equals(name)) { assertEquals(prop.getType(), "string"); } if ("name".equals(name)) { assertEquals(prop.getType(), "string"); } } } @JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.NAME, property = "type", visible = true) @JsonSubTypes({@JsonSubTypes.Type(value = Sub1Bean.class, name = "sub1")}) @io.swagger.v3.oas.annotations.media.Schema(description = "BaseBean" , discriminatorProperty = "type", discriminatorMapping = {@DiscriminatorMapping(value = "Sub1BeanMapped", schema = Sub1Bean.class)} ) static class BaseBean { public String type; public int a; public String b; } @io.swagger.v3.oas.annotations.media.Schema(description = "Sub1Bean", allOf = {BaseBean.class}) static class Sub1Bean extends BaseBean { public int c; } @JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.NAME, property = "type", visible = true) @JsonSubTypes({@JsonSubTypes.Type(value = Sub2Bean.class, name = "sub2")}) @io.swagger.v3.oas.annotations.media.Schema(description = "BaseBean2") static class BaseBean2 { public String type; public int a; public String b; public int getD() { return d; } public void setD(int d) { this.d = d; } private int d; } @io.swagger.v3.oas.annotations.media.Schema(description = "Sub2Bean", allOf = {BaseBean2.class}, anyOf = {BaseBean.class}) static class Sub2Bean extends BaseBean2 { public int a; public int c; } @JsonSubTypes({@JsonSubTypes.Type(value = ChildBean3.class, name = "childBean3")}) @io.swagger.v3.oas.annotations.media.Schema(description = "BaseBean3" , discriminatorProperty = "type", discriminatorMapping = {@DiscriminatorMapping(value = "ChildBean3Mapped", schema = ChildBean3.class)} ) static class BaseBean3 { public String type; public int a; public String b; } @JsonSubTypes({@JsonSubTypes.Type(value = GrandChildBean3.class, name = "grandChildBean3")}) @io.swagger.v3.oas.annotations.media.Schema(description = "ChildBean3", allOf = {BaseBean3.class}) static class ChildBean3 extends BaseBean3 { public int c; } @io.swagger.v3.oas.annotations.media.Schema(description = "GrandChildBean3", allOf = {ChildBean3.class}) static class GrandChildBean3 extends ChildBean3 { public int d; } @io.swagger.v3.oas.annotations.media.Schema(anyOf = {UserObject.class, EmployeeObject.class}) static class UberObject implements UserObject, EmployeeObject { private String id; private String name; private String department; @Override public String getDepartment() { return department; } @Override public String getId() { return id; } @Override public String getName() { return name; } } @io.swagger.v3.oas.annotations.media.Schema(description = "A User Object") interface UserObject { @io.swagger.v3.oas.annotations.media.Schema(format = "uuid", required = true) String getId(); String getName(); } @io.swagger.v3.oas.annotations.media.Schema(description = "An Employee Object", requiredProperties = {"department"}) interface EmployeeObject { @io.swagger.v3.oas.annotations.media.Schema(format = "email") String getId(); String getDepartment(); } @Test public void testMultipleInheritedBean() throws Exception { final Schema baseModel = context.resolve(new AnnotatedType(MultipleBaseBean.class)); assertNotNull(baseModel); assertBasePropertiesValid(baseModel.getProperties()); final Schema sub1Model = context.getDefinedModels().get("MultipleSub1Bean"); assertNotNull(sub1Model); // make sure child points at parent assertTrue(sub1Model instanceof ComposedSchema); ComposedSchema cm1 = (ComposedSchema) sub1Model; assertEquals(cm1.getAllOf().get(0).get$ref(), "#/components/schemas/MultipleBaseBean"); // make sure parent properties are filtered out of subclass assertSub1PropertiesValid(cm1.getAllOf().get(1).getProperties()); final Schema sub2Model = context.getDefinedModels().get("MultipleSub2Bean"); assertNotNull(sub2Model); assertTrue(sub2Model instanceof ComposedSchema); ComposedSchema cm2 = (ComposedSchema) sub2Model; assertEquals(cm2.getAllOf().get(0).get$ref(), "#/components/schemas/MultipleBaseBean"); // make sure parent properties are filtered out of subclass assertSub2PropertiesValid(cm2.getAllOf().get(1).getProperties()); } @Test public void testMultipleInheritedChildBean() throws Exception { final Schema subModel = context.resolve(new AnnotatedType(MultipleSub1Bean.class)); assertNotNull(subModel); // make sure child points at parent assertTrue(subModel instanceof ComposedSchema); ComposedSchema cm = (ComposedSchema) subModel; assertEquals(cm.getAllOf().get(0).get$ref(), "#/components/schemas/MultipleBaseBean"); // make sure parent properties are filtered out of subclass assertSub1PropertiesValid(cm.getAllOf().get(1).getProperties()); final Schema baseModel = context.getDefinedModels().get("MultipleBaseBean"); assertNotNull(baseModel); assertBasePropertiesValid(baseModel.getProperties()); final Schema sub1Model = context.getDefinedModels().get("MultipleSub1Bean"); assertNotNull(sub1Model); // make sure child points at parent assertTrue(sub1Model instanceof ComposedSchema); ComposedSchema cm1 = (ComposedSchema) sub1Model; assertEquals(cm1.getAllOf().get(0).get$ref(), "#/components/schemas/MultipleBaseBean"); // make sure parent properties are filtered out of subclass assertSub1PropertiesValid(cm1.getAllOf().get(1).getProperties()); final Schema sub2Model = context.getDefinedModels().get("MultipleSub2Bean"); assertNotNull(sub2Model); assertTrue(sub2Model instanceof ComposedSchema); ComposedSchema cm2 = (ComposedSchema) sub2Model; assertEquals(cm2.getAllOf().get(0).get$ref(), "#/components/schemas/MultipleBaseBean"); // make sure parent properties are filtered out of subclass assertSub2PropertiesValid(cm2.getAllOf().get(1).getProperties()); } private void assertSub2PropertiesValid(Map subProperties) { assertEquals(subProperties.size(), 1); for (Map.Entry entry : subProperties.entrySet()) { final String name = entry.getKey(); final Schema prop = entry.getValue(); if ("d".equals(name)) { assertEquals(prop.getType(), "integer"); assertEquals(prop.getFormat(), "int32"); } } } @JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.NAME, property = "type", visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = MultipleSub1Bean.class, name = "multipleSub1"), @JsonSubTypes.Type(value = MultipleSub2Bean.class, name = "multipleSub2") }) @io.swagger.v3.oas.annotations.media.Schema(description = "MultipleBaseBean") static class MultipleBaseBean { public String type; public int a; public String b; } @io.swagger.v3.oas.annotations.media.Schema(description = "MultipleSub1Bean", allOf = {MultipleBaseBean.class}) static class MultipleSub1Bean extends MultipleBaseBean { public int c; } @io.swagger.v3.oas.annotations.media.Schema(description = "MultipleSub2Bean", allOf = {MultipleBaseBean.class}) static class MultipleSub2Bean extends MultipleBaseBean { public int d; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/InlineResolvingTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.annotations.media.Schema; import org.testng.annotations.Test; public class InlineResolvingTest extends SwaggerTestBase{ @Test public void testInlineResolving() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(false).schemaResolution(io.swagger.v3.oas.models.media.Schema.SchemaResolution.INLINE); final ModelConverterContextImpl c = new ModelConverterContextImpl(modelResolver); // ModelConverters c = ModelConverters.getInstance(false, io.swagger.v3.oas.models.media.Schema.SchemaResolution.INLINE); c.resolve(new AnnotatedType(InlineSchemaFirst.class)); String expectedYaml = "InlineSchemaFirst:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " description: InlineSchemaFirst property 1\n" + " nullable: true\n" + " example: example\n" + " property2:\n" + " type: object\n" + " description: ' InlineSchemaFirst property 2'\n" + " example: example 2\n" + "InlineSchemaPropertyFirst:\n" + " type: object\n" + " description: property\n" + " example: example\n"; SerializationMatchers.assertEqualsToYaml(c.getDefinedModels(), expectedYaml); // stringSchemaMap = c.readAll(InlineSchemaSecond.class); c.resolve(new AnnotatedType(InlineSchemaSecond.class)); expectedYaml = "InlineSchemaFirst:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " description: InlineSchemaFirst property 1\n" + " nullable: true\n" + " example: example\n" + " property2:\n" + " type: object\n" + " description: ' InlineSchemaFirst property 2'\n" + " example: example 2\n" + "InlineSchemaPropertyFirst:\n" + " type: object\n" + " description: property\n" + " example: example\n" + "InlineSchemaPropertySecond:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " description: property 2\n" + " example: example\n" + " description: propertysecond\n" + " nullable: true\n" + " example: examplesecond\n" + "InlineSchemaPropertySimple:\n" + " type: object\n" + " description: property\n" + " example: example\n" + "InlineSchemaSecond:\n" + " type: object\n" + " properties:\n" + " propertySecond1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " description: property 2\n" + " example: example\n" + " description: InlineSchemaSecond property 1\n" + " nullable: true\n" + " example: examplesecond\n" + " property2:\n" + " type: object\n" + " description: InlineSchemaSecond property 2\n" + " example: InlineSchemaSecond example 2\n" + "InlineSchemaSimple:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " description: property 2\n" + " example: example\n"; SerializationMatchers.assertEqualsToYaml(c.getDefinedModels(), expectedYaml); } static class InlineSchemaFirst { // public String foo; @Schema(description = "InlineSchemaFirst property 1", nullable = true) public InlineSchemaPropertyFirst property1; private InlineSchemaPropertyFirst property2; @Schema(description = " InlineSchemaFirst property 2", example = "example 2") public InlineSchemaPropertyFirst getProperty2() { return null; } } static class InlineSchemaSecond { // public String foo; @Schema(description = "InlineSchemaSecond property 1", nullable = true) public InlineSchemaPropertySecond propertySecond1; private InlineSchemaPropertyFirst property2; @Schema(description = "InlineSchemaSecond property 2", example = "InlineSchemaSecond example 2") public InlineSchemaPropertyFirst getProperty2() { return null; } } @Schema(description = "property", example = "example") static class InlineSchemaPropertyFirst { // public String bar; } @Schema(description = "propertysecond", example = "examplesecond") static class InlineSchemaPropertySecond { public InlineSchemaSimple bar; } static class InlineSchemaSimple { @Schema(description = "property 1") public InlineSchemaPropertySimple property1; private InlineSchemaPropertySimple property2; @Schema(description = "property 2", example = "example") public InlineSchemaPropertySimple getProperty2() { return null; } } @Schema(description = "property") static class InlineSchemaPropertySimple { // public String bar; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/JacksonJsonUnwrappedTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.JacksonUnwrappedRequiredProperty; import org.testng.annotations.Test; public class JacksonJsonUnwrappedTest { @Test(description = "test the @JsonUnwrapped behaviour when required Properties") public void jacksonJsonUnwrappedTest() { SerializationMatchers .assertEqualsToYaml(ModelConverters.getInstance().read( JacksonUnwrappedRequiredProperty.class), "InnerTypeRequired:\n" + " required:\n" + " - name\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: integer\n" + " format: int32\n" + " name:\n" + " type: string\n" + "JacksonUnwrappedRequiredProperty:\n" + " required:\n" + " - name\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: integer\n" + " format: int32\n" + " name:\n" + " type: string\n"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/JaxBDefaultValueTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.oas.models.ModelWithJaxBDefaultValues; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; public class JaxBDefaultValueTest { @Test(description = "convert a model with Guava optionals") public void convertModelWithGuavaOptionals() { final Map schemas = ModelConverters.getInstance().read(ModelWithJaxBDefaultValues.class); final Map properties = schemas.get("ModelWithJaxBDefaultValues").getProperties(); assertEquals(properties.size(), 2); assertEquals(((StringSchema) properties.get("name")).getDefault(), "Tony"); assertEquals((int) ((IntegerSchema) properties.get("age")).getDefault(), 100); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/JodaDateTimeConverterTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.joda.time.DateTime; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class JodaDateTimeConverterTest { @Test public void testJodaDateTime() { final Map models = ModelConverters.getInstance().read(ModelWithJodaDateTime.class); assertEquals(models.size(), 1); // don't create a Joda DateTime object final Schema model = models.get("ModelWithJodaDateTime"); final Schema dateTimeProperty = (Schema) model.getProperties().get("createdAt"); assertTrue(dateTimeProperty instanceof DateTimeSchema); assertTrue(model.getRequired().contains("createdAt")); assertEquals(dateTimeProperty.getDescription(), "creation timestamp"); final Schema nameProperty = (Schema) model.getProperties().get("name"); assertTrue(nameProperty instanceof StringSchema); assertEquals(nameProperty.getDescription(), "name of the model"); } class ModelWithJodaDateTime { @io.swagger.v3.oas.annotations.media.Schema(description = "name of the model") public String name; @io.swagger.v3.oas.annotations.media.Schema(description = "creation timestamp", required = true) public DateTime createdAt; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/JodaLocalDateConverterTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.oas.models.media.DateSchema; import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.joda.time.LocalDate; import org.testng.annotations.Test; import java.time.Instant; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class JodaLocalDateConverterTest { @Test public void testJodaLocalDate() { final Map models = ModelConverters.getInstance().read(ModelWithJodaLocalDate.class); assertEquals(models.size(), 1); final Schema model = models.get("ModelWithJodaLocalDate"); final Schema dateTimeProperty = (Schema) model.getProperties().get("createdAt"); assertTrue(dateTimeProperty instanceof DateSchema); assertTrue(model.getRequired().contains("createdAt")); assertEquals(dateTimeProperty.getDescription(), "creation localDate"); final Schema nameProperty = (Schema) model.getProperties().get("name"); assertTrue(nameProperty instanceof StringSchema); assertEquals(nameProperty.getDescription(), "name of the model"); } class ModelWithJodaLocalDate { @io.swagger.v3.oas.annotations.media.Schema(description = "name of the model") public String name; @io.swagger.v3.oas.annotations.media.Schema(description = "creation localDate", required = true) public LocalDate createdAt; } @Test public void testJavaTimeInstant() { final Map models = ModelConverters.getInstance().read(ModelWithJavaTimeInstant.class); assertEquals(models.size(), 1); final Schema model = models.get("ModelWithJavaTimeInstant"); final Schema dateTimeProperty = (Schema) model.getProperties().get("createdAt"); assertTrue(dateTimeProperty instanceof DateTimeSchema); } class ModelWithJavaTimeInstant { @io.swagger.v3.oas.annotations.media.Schema(description = "name of the model") public String name; public Instant createdAt; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/JodaTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.oas.models.media.Schema; import org.joda.time.DateTime; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.FileAssert.fail; public class JodaTest extends SwaggerTestBase { @Test public void testSimple() throws Exception { final ModelConverter mr = modelResolver(); final Schema model = mr.resolve(new AnnotatedType(ModelWithJodaDateTime.class), new ModelConverterContextImpl(mr), null); assertNotNull(model); final Map props = model.getProperties(); assertEquals(props.size(), 2); for (Map.Entry entry : props.entrySet()) { final String name = entry.getKey(); final Schema prop = entry.getValue(); if ("name".equals(name)) { assertEquals(prop.getType(), "string"); } else if ("createdAt".equals(name)) { assertEquals(prop.getType(), "string"); assertEquals(prop.getFormat(), "date-time"); } else { fail(String.format("Unknown property '%s'", name)); } } } static class ModelWithJodaDateTime { @io.swagger.v3.oas.annotations.media.Schema(description = "Name!") public String name; @io.swagger.v3.oas.annotations.media.Schema(description = "creation timestamp", required = true) public DateTime createdAt; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/JsonPropertyTest.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.User2169; import org.testng.annotations.Test; public class JsonPropertyTest { @Test(description = "test ticket 2169") public void testTicket2169() { SerializationMatchers.assertEqualsToYaml(ModelConverters.getInstance().read(User2169.class), "User2169:\n" + " required:\n" + " - Age\n" + " - GetterJsonPropertyOnField\n" + " - GetterJsonPropertyOnFieldReadOnly\n" + " - GetterJsonPropertyOnFieldReadWrite\n" + " - GetterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse\n" + " - GetterJsonPropertyOnFieldReadWriteSchemaReadOnlyFalse\n" + " - GetterJsonPropertyOnFieldSchemaReadOnlyTrue\n" + " - Name\n" + " type: object\n" + " properties:\n" + " Name:\n" + " type: string\n" + " Age:\n" + " type: integer\n" + " format: int32\n" + " GetterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse:\n" + " type: string\n" + " publi:\n" + " type: string\n" + " getter:\n" + " type: string\n" + " setter:\n" + " type: string\n" + " writeOnly: true\n" + " getterSetter:\n" + " type: string\n" + " jsonProp:\n" + " type: string\n" + " jsonPropReadOnly:\n" + " type: string\n" + " readOnly: true\n" + " jsonPropWriteOnly:\n" + " type: string\n" + " writeOnly: true\n" + " jsonPropReadWrite:\n" + " type: string\n" + " getter_jsonProp:\n" + " type: string\n" + " getter_jsonPropReadOnly:\n" + " type: string\n" + " readOnly: true\n" + " getter_jsonPropWriteOnly:\n" + " type: string\n" + " getter_jsonPropReadWrite:\n" + " type: string\n" + " setter_jsonProp:\n" + " type: string\n" + " writeOnly: true\n" + " setter_jsonPropReadOnly:\n" + " type: string\n" + " setter_jsonPropWriteOnly:\n" + " type: string\n" + " writeOnly: true\n" + " setter_jsonPropReadWrite:\n" + " type: string\n" + " gettersetter_jsonPropGet:\n" + " type: string\n" + " gettersetter_jsonPropReadOnlyGet:\n" + " type: string\n" + " readOnly: true\n" + " gettersetter_jsonPropWriteOnlyGet:\n" + " type: string\n" + " gettersetter_jsonPropReadWriteGet:\n" + " type: string\n" + " gettersetter_jsonPropSet:\n" + " type: string\n" + " gettersetter_jsonPropReadOnlySet:\n" + " type: string\n" + " gettersetter_jsonPropWriteOnlySet:\n" + " type: string\n" + " writeOnly: true\n" + " gettersetter_jsonPropReadWriteSet:\n" + " type: string\n" + " getterIgnore_jsonPropSet:\n" + " type: string\n" + " writeOnly: true\n" + " getterIgnore_jsonPropReadOnlySet:\n" + " type: string\n" + " getterIgnore_jsonPropWriteOnlySet:\n" + " type: string\n" + " writeOnly: true\n" + " getterIgnore_jsonPropReadWriteSet:\n" + " type: string\n" + " setterIgnore_jsonPropGet:\n" + " type: string\n" + " setterIgnore_jsonPropReadOnlyGet:\n" + " type: string\n" + " readOnly: true\n" + " setterIgnore_jsonPropWriteOnlyGet:\n" + " type: string\n" + " setterIgnore_jsonPropReadWriteGet:\n" + " type: string\n" + " getterSchemaReadOnlyTrue:\n" + " type: string\n" + " readOnly: true\n" + " data:\n" + " $ref: \"#/components/schemas/Data\"\n" + " GetterJsonPropertyOnField:\n" + " type: string\n" + " GetterJsonPropertyOnFieldReadWrite:\n" + " type: string\n" + " GetterJsonPropertyOnFieldReadWriteSchemaReadOnlyFalse:\n" + " type: string\n" + " GetterJsonPropertyOnFieldReadOnly:\n" + " type: string\n" + " readOnly: true\n" + " GetterJsonPropertyOnFieldSchemaReadOnlyTrue:\n" + " type: string\n" + " readOnly: true\n" + " approvePairing:\n" + " type: boolean\n" + " writeOnly: true\n"); } @Test(description = "test ticket 2845") public void testTicket2845() { SerializationMatchers.assertEqualsToYaml(ModelConverters.getInstance().readAll(Ticket2845Holder.class), "Ticket2845Child:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " meow:\n" + " type: string\n" + "Ticket2845Holder:\n" + " type: object\n" + " properties:\n" + " child:\n" + " $ref: \"#/components/schemas/Ticket2845Child\""); /* TODO: Test demonstrating annotation not being resolved when class is used/refernces elsewhere with different annotations in this case the annotation isn't resolved or not consistently resolved as the same object is also present and referenced (in the same or different class) with no or different @JsonIgnoreProperties annotations. The possible solutions are either resolve into different unrelated schemas or resolve inline (see https://github.com/swagger-api/swagger-core/issues/3366 and other related tickets) */ SerializationMatchers.assertEqualsToYaml( ModelConverters.getInstance().readAll(Ticket2845HolderNoAnnotationNotWorking.class), "Ticket2845Child:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " bar:\n" + " type: string\n" + " meow:\n" + " type: string\n" + "Ticket2845HolderNoAnnotationNotWorking:\n" + " type: object\n" + " properties:\n" + " child:\n" + " $ref: \"#/components/schemas/Ticket2845Child\"\n" + " childNoAnnotation:\n" + " $ref: \"#/components/schemas/Ticket2845Child\""); } static class Ticket2845Parent { public String foo; public String bar; public String bob; } @JsonIgnoreProperties({"bob"}) static class Ticket2845Child extends Ticket2845Parent { public String meow; } static class Ticket2845Holder { @JsonIgnoreProperties({"foo"}) public Ticket2845Child child; } static class Ticket2845HolderNoAnnotationNotWorking { @JsonIgnoreProperties({"foo"}) public Ticket2845Child child; public Ticket2845Child childNoAnnotation; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/JsonSubTypesAndSchemaOneOfTest.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.*; public class JsonSubTypesAndSchemaOneOfTest extends SwaggerTestBase { private static final String BASE_PROPERTY = "a"; private static final String BASE_PROPERTY_2 = "b"; private static final String SUB_BEAN_1_NAME = "SubBean1"; private static final String SUB_BEAN_2_NAME = "SubBean2"; private static final String SUB_BEAN_INTERFACE_1_NAME = "SubBean1InterfaceImplementor"; private static final String SUB_BEAN_INTERFACE_2_NAME = "SubBean2InterfaceImplementor"; private static final String CHILD_1_PROPERTY = "c"; private static final String CHILD_2_PROPERTY = "d"; private static final String DISCRIMINATOR_PROPERTY_NAME = "type"; private ModelConverterContextImpl context; @BeforeMethod public void setup() { ModelResolver.composedModelPropertiesAsSibling = false; ModelResolver modelResolver = new ModelResolver(new ObjectMapper()); context = new ModelConverterContextImpl(modelResolver); } @AfterTest public void afterTest() { ModelResolver.composedModelPropertiesAsSibling = false; } @Test public void beanWithJsonSubTypesAndSchemaOneOfHasAllOfAndOneOfInModelSchemaObject() { final Schema baseModel = context.resolve(new AnnotatedType(BaseBean.class)); assertNotNull(baseModel); assertBasePropertiesValid(baseModel.getProperties()); // The base class contains a oneOf-definition which will make the child classes have a recursive reference. // Child's allOf -> Parent -> Parent's oneOf -> Child -> Child's allOf -> ... assertNotNull(baseModel.getOneOf()); assertEquals(baseModel.getOneOf().size(), 2); assertEquals(baseModel.getDiscriminator().getPropertyName(), DISCRIMINATOR_PROPERTY_NAME); assertEquals(baseModel.getDiscriminator().getMapping().get(SUB_BEAN_1_NAME), "#/components/schemas/SubBean1"); assertEquals(baseModel.getDiscriminator().getMapping().get(SUB_BEAN_2_NAME), "#/components/schemas/SubBean2"); final Schema subModel1 = context.getDefinedModels().get(SUB_BEAN_1_NAME); assertNotNull(subModel1); // make sure child points at parent assertTrue(subModel1 instanceof ComposedSchema); ComposedSchema cm1 = (ComposedSchema) subModel1; assertEquals(cm1.getAllOf().get(0).get$ref(), "#/components/schemas/BaseBean"); // make sure parent properties are filtered out of subclass assertSubPropertiesValid(cm1.getAllOf().get(1).getProperties(), CHILD_1_PROPERTY); final Schema subModel2 = context.getDefinedModels().get(SUB_BEAN_2_NAME); assertNotNull(subModel2); // make sure child points at parent assertTrue(subModel2 instanceof ComposedSchema); ComposedSchema cm2 = (ComposedSchema) subModel2; assertEquals(cm2.getAllOf().get(0).get$ref(), "#/components/schemas/BaseBean"); // make sure parent properties are filtered out of subclass assertSubPropertiesValid(cm1.getAllOf().get(1).getProperties(), CHILD_2_PROPERTY); } private void assertBasePropertiesValid(Map baseProperties) { assertEquals(baseProperties.size(), 3); for (Map.Entry entry : baseProperties.entrySet()) { final String name = entry.getKey(); final Schema prop = entry.getValue(); if ("type".equals(name)) { assertEquals(prop.getType(), "string"); } else if (BASE_PROPERTY.equals(name)) { assertEquals(prop.getType(), "integer"); assertEquals(prop.getFormat(), "int32"); } else if (BASE_PROPERTY_2.equals(name)) { assertEquals(prop.getType(), "string"); } } } @JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.NAME, property = "type", visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = SubBean1.class, name = "SubBean1"), @JsonSubTypes.Type(value = SubBean2.class, name = "SubBean2") }) @io.swagger.v3.oas.annotations.media.Schema( description = "BaseBean", discriminatorProperty = "type", discriminatorMapping = { @DiscriminatorMapping(value = "SubBean1", schema = SubBean1.class), @DiscriminatorMapping(value = "SubBean2", schema = SubBean2.class) }, oneOf = {SubBean1.class, SubBean2.class} ) static class BaseBean { public String type; public int a; public String b; } static class SubBean1 extends BaseBean { public int a; public int c; } static class SubBean2 extends BaseBean { public int a; public int d; } @Test public void beanWithJsonSubTypesImplementsBeanWithSchemaOneOfHasOnlyOneOfInModelSchemaObject() { final Schema baseModel = context.resolve(new AnnotatedType(BaseBeanInterfaceImplementor.class)); assertNotNull(baseModel); assertNull(baseModel.getProperties()); assertEquals(baseModel.getDiscriminator().getPropertyName(), DISCRIMINATOR_PROPERTY_NAME); assertEquals(baseModel.getDiscriminator().getMapping().get(SUB_BEAN_INTERFACE_1_NAME), "#/components/schemas/SubBean1InterfaceImplementor"); assertEquals(baseModel.getDiscriminator().getMapping().get(SUB_BEAN_INTERFACE_2_NAME), "#/components/schemas/SubBean2InterfaceImplementor"); final Schema subModel1 = context.getDefinedModels().get(SUB_BEAN_INTERFACE_1_NAME); assertNotNull(subModel1); //We should not have a parent in the schema assertNull(subModel1.getAllOf()); //The child should have the parent's properties and its own assertEquals(subModel1.getProperties().size(), 4); assertNotNull(subModel1.getProperties().get(CHILD_1_PROPERTY)); final Schema subModel2 = context.getDefinedModels().get(SUB_BEAN_INTERFACE_2_NAME); assertNotNull(subModel2); //We should not have a parent in the schema assertNull(subModel2.getAllOf()); //The child should have the parent's properties and its own assertEquals(subModel2.getProperties().size(), 4); assertNotNull(subModel2.getProperties().get(CHILD_2_PROPERTY)); } @io.swagger.v3.oas.annotations.media.Schema( description = "InterfaceBean", discriminatorProperty = "type", discriminatorMapping = { @DiscriminatorMapping(value = "SubBean1InterfaceImplementor", schema = SubBean1InterfaceImplementor.class), @DiscriminatorMapping(value = "SubBean2InterfaceImplementor", schema = SubBean2InterfaceImplementor.class) }, oneOf = {SubBean1.class, SubBean2.class} ) interface InterfaceBean { String type(); int a(); String b(); } @JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.NAME, property = "type", visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = SubBean1InterfaceImplementor.class, name = "SubBean1InterfaceImplementor"), @JsonSubTypes.Type(value = SubBean2InterfaceImplementor.class, name = "SubBean2InterfaceImplementor") }) @io.swagger.v3.oas.annotations.media.Schema(implementation = InterfaceBean.class) static class BaseBeanInterfaceImplementor { public String type; public int a; public String b; } static class SubBean1InterfaceImplementor extends BaseBeanInterfaceImplementor { public int c; } static class SubBean2InterfaceImplementor extends BaseBeanInterfaceImplementor { public int d; } private void assertSubPropertiesValid(Map subProperties, final String childPropertyName) { assertEquals(subProperties.size(), 1); for (Map.Entry entry : subProperties.entrySet()) { final String name = entry.getKey(); final Schema prop = entry.getValue(); if (childPropertyName.equals(name)) { assertEquals(prop.getType(), "integer"); assertEquals(prop.getFormat(), "int32"); } } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/JsonViewTest.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.resolving.resources.JsonViewObject; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.lang.annotation.Annotation; import java.util.Map; import static io.swagger.v3.core.resolving.SwaggerTestBase.mapper; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class JsonViewTest { @Test @JsonView(JsonViewObject.View.Protected.class) public void includePropertiesToWhichJsonviewIsNotAnnotated() throws NoSuchMethodException { ObjectMapper mapper = mapper(); final ModelResolver modelResolver = new ModelResolver(mapper); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(JsonViewObject.Person.class) .jsonViewAnnotation(new JsonView() { public Class annotationType() { return JsonView.class; } public Class[] value() { return new Class[] {JsonViewObject.View.Protected.class}; } }) .ctxAnnotations( this.getClass() .getMethod("includePropertiesToWhichJsonviewIsNotAnnotated") .getAnnotations())); Map properties = model.getProperties(); assertEquals(properties.size(), 4); assertNotNull(properties.get("id")); assertNotNull(properties.get("firstName")); assertNotNull(properties.get("lastName")); assertNotNull(properties.get("email")); } @Test @JsonView(JsonViewObject.View.Protected.class) public void notIncludePropertiesToWhichJsonviewIsNotAnnotated() throws NoSuchMethodException { ObjectMapper mapper = mapper(); mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION); final ModelResolver modelResolver = new ModelResolver(mapper); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(JsonViewObject.Person.class) .jsonViewAnnotation(new JsonView() { public Class annotationType() { return JsonView.class; } public Class[] value() { return new Class[] {JsonViewObject.View.Protected.class}; } }) .includePropertiesWithoutJSONView(false) .ctxAnnotations( this.getClass() .getMethod("includePropertiesToWhichJsonviewIsNotAnnotated") .getAnnotations())); Map properties = model.getProperties(); assertEquals(properties.size(), 3); assertNotNull(properties.get("id")); assertNotNull(properties.get("firstName")); assertNotNull(properties.get("lastName")); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/ModelWithRangesTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.oas.models.ModelWithRanges; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.NumberSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.math.BigDecimal; import java.util.Arrays; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; public class ModelWithRangesTest { @Test(description = "test model with @ApiModelProperty.allowableValues") public void modelWithRangesTest() { final Map properties = ModelConverters.getInstance().read(ModelWithRanges.class).get("ModelWithRanges").getProperties(); final IntegerSchema inclusiveRange = (IntegerSchema) properties.get("inclusiveRange"); assertEquals(inclusiveRange.getMinimum(), new BigDecimal(1)); assertEquals(inclusiveRange.getMaximum(), new BigDecimal(5)); assertNull(inclusiveRange.getExclusiveMaximum()); assertNull(inclusiveRange.getExclusiveMinimum()); final IntegerSchema exclusiveRange = (IntegerSchema) properties.get("exclusiveRange"); assertEquals(exclusiveRange.getMinimum(), new BigDecimal(1)); assertEquals(exclusiveRange.getMaximum(), new BigDecimal(5)); assertEquals(exclusiveRange.getExclusiveMinimum(), Boolean.TRUE); assertEquals(exclusiveRange.getExclusiveMaximum(), Boolean.TRUE); final IntegerSchema positiveInfinityRange = (IntegerSchema) properties.get("positiveInfinityRange"); assertEquals(positiveInfinityRange.getMinimum(), new BigDecimal(1.0)); assertNull(positiveInfinityRange.getMaximum()); assertNull(positiveInfinityRange.getExclusiveMaximum()); assertNull(positiveInfinityRange.getExclusiveMinimum()); final IntegerSchema negativeInfinityRange = (IntegerSchema) properties.get("negativeInfinityRange"); assertNull(negativeInfinityRange.getMinimum()); assertEquals(negativeInfinityRange.getMaximum(), new BigDecimal(5.0)); assertNull(negativeInfinityRange.getExclusiveMaximum()); assertNull(negativeInfinityRange.getExclusiveMinimum()); final StringSchema stringValues = (StringSchema) properties.get("stringValues"); assertEquals(stringValues.getEnum(), Arrays.asList("str1", "str2")); final NumberSchema doubleValues = (NumberSchema) properties.get("doubleValues"); assertEquals(doubleValues.getMinimum(), new BigDecimal("1.0")); assertEquals(doubleValues.getMaximum(), new BigDecimal("8.0")); assertEquals(doubleValues.getExclusiveMaximum(), Boolean.TRUE); assertNull(doubleValues.getExclusiveMinimum()); final IntegerSchema intAllowableValues = (IntegerSchema) properties.get("intAllowableValues"); assertEquals(intAllowableValues.getEnum(), Arrays.asList(1, 2)); final IntegerSchema intAllowableValuesWithNull = (IntegerSchema) properties.get("intAllowableValuesWithNull"); assertEquals(intAllowableValuesWithNull.getEnum(), Arrays.asList(1, 2, null)); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/RequiredFieldModelTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.oas.models.ApiFirstRequiredFieldModel; import io.swagger.v3.core.oas.models.RequiredRefFieldModel; import io.swagger.v3.core.oas.models.XmlFirstRequiredFieldModel; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class RequiredFieldModelTest { @Test(description = "it should apply required flag when ApiProperty annotation first") public void testApiModelPropertyFirstPosition() { final Map models = ModelConverters.getInstance().readAll(ApiFirstRequiredFieldModel.class); final Schema model = models.get("aaa"); final Schema prop = (Schema) model.getProperties().get("bla"); assertNotNull(prop); assertTrue(model.getRequired().contains("bla")); } @Test(description = "it should apply required flag when XmlElement annotation first") public void testApiModelPropertySecondPosition() { final Map models = ModelConverters.getInstance().readAll(XmlFirstRequiredFieldModel.class); final Schema model = models.get("aaa"); final Schema prop = (Schema) model.getProperties().get("a"); assertNotNull(prop); assertTrue(model.getRequired().contains("a")); } @Test(description = "it should apply required flag also to ref fields") public void testApiModelRefProperty() { final Map models = ModelConverters.getInstance().readAll(RequiredRefFieldModel.class); final Schema model = models.get("RequiredRefFieldModel"); final Schema prop = (Schema) model.getProperties().get("a"); assertNotNull(prop); final Schema prop2 = (Schema) model.getProperties().get("b"); assertNotNull(prop2); assertTrue(model.getRequired().contains("a")); assertTrue(model.getRequired().contains("b")); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/SimpleGenerationTest.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.fail; public class SimpleGenerationTest extends SwaggerTestBase { private final ModelResolver modelResolver = new ModelResolver(new ObjectMapper()); private final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); @Test public void testSimple() throws Exception { final Schema model = context.resolve(new AnnotatedType(SimpleBean.class)); assertNotNull(model); assertEquals(model.getDescription(), "DESC"); final Map props = model.getProperties(); assertEquals(props.size(), 6); for (Map.Entry entry : props.entrySet()) { final String name = entry.getKey(); final Schema prop = entry.getValue(); if ("a".equals(name)) { assertEquals(prop.getType(), "string"); } else if ("b".equals(name)) { assertEquals(prop.getType(), "integer"); assertEquals(prop.getFormat(), "int32"); } else if ("c".equals(name)) { assertEquals(prop.getType(), "integer"); assertEquals(prop.getFormat(), "int64"); } else if ("d".equals(name)) { assertEquals(prop.getType(), "number"); assertEquals(prop.getFormat(), "float"); } else if ("e".equals(name)) { assertEquals(prop.getType(), "number"); assertEquals(prop.getFormat(), "double"); } else if ("f".equals(name)) { assertEquals(prop.getType(), "string"); assertEquals(prop.getFormat(), "date-time"); } else { fail(String.format("Unknown property '%s'", name)); } } } @Test public void testOrdering() throws Exception { final Schema jsonOrderBean = context.resolve(new AnnotatedType(JsonOrderBean.class)); final Map props = jsonOrderBean.getProperties(); assertEquals(new ArrayList(props.keySet()), Arrays.asList("a", "b", "c", "d")); } @Test public void testTheCountBean() throws Exception { final Schema model = context.resolve(new AnnotatedType(TheCount.class)); final Map props = model.getProperties(); assertEquals(props.size(), 1); String key = props.keySet().iterator().next(); final Schema prop = props.get(key); assertEquals(key, "theCount"); } @Test public void testStringDateMap() throws Exception { final Schema model = context.resolve(new AnnotatedType(StringDateMapBean.class)); final Map props = model.getProperties(); assertEquals(props.size(), 1); String key = props.keySet().iterator().next(); final Schema prop = props.get(key); assertEquals(key, "stuff"); } @Test public void testIntArray() throws Exception { final Schema model = context.resolve(new AnnotatedType(IntArrayBean.class)); final Map props = model.getProperties(); assertEquals(props.size(), 1); String key = props.keySet().iterator().next(); final Schema prop = props.get(key); assertEquals(key, "b"); assertEquals(prop.getType(), "array"); } protected boolean isJacksonAtLeast2_9() throws NoSuchMethodException { try { Method m = BeanDescription.class.getMethod("findJsonValueAccessor", null); } catch (NoSuchMethodException e) { return false; } return true; } @Test public void testJsonValue_Ticket3409() throws Exception { DeserializationFeature aa = DeserializationFeature.valueOf("FAIL_ON_UNKNOWN_PROPERTIES"); Map models = ModelConverters.getInstance().readAll(PlanetName.Planet.class); assertNotNull(models.get("Planet")); if (isJacksonAtLeast2_9()) { assertNull(models.get("PlanetName")); assertEquals(((Schema) models.get("Planet").getProperties().get("name")).getType(), "string"); } } @Test public void testComplex() throws Exception { final Schema model = context.resolve(new AnnotatedType(ComplexBean.class)); assertNotNull(model); final Map props = model.getProperties(); assertEquals(props.size(), 6); } /* /********************************************************** /* Test methods /********************************************************** */ @JsonPropertyOrder({"a", "b"}) @io.swagger.v3.oas.annotations.media.Schema(description = "DESC") static class SimpleBean { public int b; public long c; public float d; public double e; public java.util.Date f; public String getA() { return null; } } @JsonPropertyOrder({"a", "b", "c", "d"}) static class JsonOrderBean { public int d; public int a; public int c; public int b; } static class TheCount { @JsonProperty("theCount") private Integer count; public Integer getCount() { return count; } public void setCount(Integer count) { this.count = count; } } static class StringDateMapBean { public Map stuff; } @JsonPropertyOrder({"a", "b"}) static class IntArrayBean { public int[] b; } static class ComplexBean { public String j; @JsonIgnore public SimpleBean simpleBean; @JsonCreator public ComplexBean(@JsonProperty("b") int b, @JsonProperty("c") long c, @JsonProperty("d") float d, @JsonProperty("e") double e, @JsonProperty("j") String j) { simpleBean = new SimpleBean(); simpleBean.b = b; simpleBean.c = c; simpleBean.d = d; simpleBean.e = e; this.j = j; } public SimpleBean getSimpleBean() { return simpleBean; } public String getA() { return simpleBean.getA(); } public int getB() { return simpleBean.b; } public long getC() { return simpleBean.c; } public float getD() { return simpleBean.d; } public double getE() { return simpleBean.e; } public String getJ() { return j; } } static class PlanetName { @JsonValue private final String value; @JsonCreator private PlanetName(String value) { this.value = value; } public static PlanetName valueOf(String value) { return new PlanetName(value); } public String getValue() { return value; } @Override public String toString() { return value; } static class Planet { private PlanetName name; public PlanetName getName() { return name; } public void setName(PlanetName name) { this.name = name; } } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/SwaggerTestBase.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import io.swagger.v3.core.jackson.ModelResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class SwaggerTestBase { static ObjectMapper mapper; private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerTestBase.class); public static ObjectMapper mapper() { if (mapper == null) { mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } return mapper; } protected ModelResolver modelResolver() { return new ModelResolver(new ObjectMapper()); } protected void prettyPrint(Object o) { try { LOGGER.debug(mapper().writer(new DefaultPrettyPrinter()).writeValueAsString(o)); } catch (Exception e) { LOGGER.error("Failed to pretty print object", e); } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket2189Test.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.ObjectMapper; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import static org.testng.Assert.assertNotNull; public class Ticket2189Test extends SwaggerTestBase { private ModelResolver modelResolver; private ModelConverterContextImpl context; @BeforeTest public void setup() { modelResolver = new ModelResolver(new ObjectMapper()); context = new ModelConverterContextImpl(modelResolver); } @Test public void testTicket2189() { final Schema model = context.resolve(new AnnotatedType(BaseClass.class)); assertNotNull(model); String yaml = "BaseClass:\n" + " type: object\n" + " properties:\n" + " property:\n" + " type: string\n" + " type:\n" + " type: string\n" + "SubClass:\n" + " type: object\n" + " allOf:\n" + " - $ref: \"#/components/schemas/BaseClass\"\n" + " - type: object\n" + " properties:\n" + " subClassProperty:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), yaml); } static class SubClass extends BaseClass { public String subClassProperty; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME) @JsonSubTypes({ @JsonSubTypes.Type(value = SubClass.class, name = "SubClass"), @JsonSubTypes.Type(value = BaseClass.class, name = "BaseClass"), }) static class BaseClass { public String property; public String type; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket2740CyclicTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.MyThing; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class Ticket2740CyclicTest extends SwaggerTestBase { @Test public void testCyclicBean() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(MyThing.class)); SerializationMatchers.assertEqualsToYaml(model, "type: object\n" + "properties:\n" + " otherThings:\n" + " uniqueItems: true\n" + " type: array\n" + " description: Other related things\n" + " items:\n" + " $ref: \"#/components/schemas/MyThing\"\n" + "description: Thing"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket2862SubtypeTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.Ticket2862Model; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class Ticket2862SubtypeTest extends SwaggerTestBase { @Test public void testSubType() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(Ticket2862Model.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "Ticket2862Model:\n" + " type: object\n" + " properties:\n" + " Ticket2862Model:\n" + " type: object\n" + "Ticket2862ModelImpl:\n" + " type: string\n" + " allOf:\n" + " - $ref: \"#/components/schemas/Ticket2862Model\"\n" + " enum:\n" + " - VALUE1\n" + " - VALUE2\n"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket2884Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.Ticket2884Model; import io.swagger.v3.core.resolving.resources.Ticket2884ModelClass; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class Ticket2884Test extends SwaggerTestBase { @Test public void test2884() { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Ticket2884ModelClass a = new Ticket2884ModelClass(); Schema model = context .resolve(new AnnotatedType(Ticket2884Model.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "Ticket2884Model:\n" + " type: object\n" + " properties:\n" + " Ticket2884Model:\n" + " type: object"); context = new ModelConverterContextImpl(modelResolver); model = context .resolve(new AnnotatedType(Ticket2884ModelClass.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "Ticket2884ModelClass:\n" + " type: object\n" + " properties:\n" + " Ticket2884ModelClass:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " foo:\n" + " type: array\n" + " items:\n" + " type: string\n"); } @Test public void test2884_null() { ResolvedSchema schema = ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType(Ticket2884ModelClass.class).resolveAsRef(true)); Schema o = (Schema)schema.schema.getProperties().get(Ticket2884ModelClass.class.getSimpleName()); assertNotNull(o); assertTrue(o.get$ref().contains(Ticket2884ModelClass.class.getSimpleName())); SerializationMatchers.assertEqualsToYaml(schema.schema.getProperties(), "Ticket2884ModelClass:\n" + " $ref: \"#/components/schemas/Ticket2884ModelClass\""); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket2915Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.TestObject2915; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class Ticket2915Test extends SwaggerTestBase { @Test public void testPropertyName() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(TestObject2915.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "QuantitativeValue:\n" + " required:\n" + " - value\n" + " type: object\n" + " properties:\n" + " value:\n" + " type: number\n" + " format: double\n" + " unitText:\n" + " type: string\n" + " unitCode:\n" + " type: string\n" + " description: A combination of a value and associated unit\n" + "TestObject2616:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " perServing:\n" + " $ref: \"#/components/schemas/QuantitativeValue\"\n" + " per100Gram:\n" + " $ref: \"#/components/schemas/QuantitativeValue\"\n" + " description: Nutritional value specification"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket2926Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.OpenAPI; import org.testng.annotations.Test; public class Ticket2926Test extends SwaggerTestBase { @Test public void testExtensionsInMapDeserializeAndSerialize() throws Exception { String yaml = "openapi: 3.0.1\n" + "info:\n" + " title: My title\n" + " description: API under test\n" + " version: 1.0.7\n" + " x-info: test\n" + "servers:\n" + "- url: http://localhost:9999/api\n" + " x-server: test\n" + " description: desc\n" + " variables: \n" + " serVar: \n" + " description: desc\n" + " x-serverVariable: test\n" + "paths:\n" + " /foo/bar:\n" + " get:\n" + " callbacks:\n" + " /foo/bar:\n" + " get:\n" + " description: getoperation\n" + " x-callback: test\n" + " responses:\n" + " default:\n" + " description: it works!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " title: inline_response_200\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " x-mediatype: test\n" + " x-response: test\n" + " x-responses: test\n" + " x-responses-object: \n" + " aaa: bbb\n" + " x-responses-array: \n" + " - aaa\n" + " - bbb\n" + " x-operation: test\n" + " x-pathitem: test\n" + " x-paths: test\n" + "x-openapi-object: \n" + " aaa: bbb\n" + "x-openapi-array: \n" + " - aaa\n" + " - bbb\n" + "x-openapi: test"; OpenAPI aa = Yaml.mapper().readValue(yaml, OpenAPI.class); SerializationMatchers.assertEqualsToYaml(aa, yaml); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket2972Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.TestObject2972; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class Ticket2972Test extends SwaggerTestBase { @Test public void testLocalTime() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(TestObject2972.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "TestObject2972:\n" + " type: object\n" + " properties:\n" + " myField1:\n" + " type: object\n" + " additionalProperties:\n" + " type: string\n" + " myField2:\n" + " type: object\n" + " additionalProperties:\n" + " type: string"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket2992Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.TestObject2992; import io.swagger.v3.core.util.PrimitiveType; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class Ticket2992Test extends SwaggerTestBase { @Test public void testLocalTime() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(TestObject2992.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "LocalTime:\n" + " type: object\n" + " properties:\n" + " hour:\n" + " type: integer\n" + " format: int32\n" + " minute:\n" + " type: integer\n" + " format: int32\n" + " second:\n" + " type: integer\n" + " format: int32\n" + " nano:\n" + " type: integer\n" + " format: int32\n" + "TestObject2992:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " a:\n" + " $ref: \"#/components/schemas/LocalTime\"\n" + " b:\n" + " $ref: \"#/components/schemas/LocalTime\"\n" + " c:\n" + " $ref: \"#/components/schemas/LocalTime\"\n" + " d:\n" + " type: string\n" + " format: date-time\n" + " e:\n" + " type: string\n" + " format: date-time\n" + " f:\n" + " type: string\n" + " format: date-time"); PrimitiveType.enablePartialTime(); context = new ModelConverterContextImpl(modelResolver); context .resolve(new AnnotatedType(TestObject2992.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "TestObject2992:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " a:\n" + " type: string\n" + " format: partial-time\n" + " b:\n" + " type: string\n" + " format: partial-time\n" + " c:\n" + " type: string\n" + " format: partial-time\n" + " d:\n" + " type: string\n" + " format: date-time\n" + " e:\n" + " type: string\n" + " format: date-time\n" + " f:\n" + " type: string\n" + " format: date-time"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3030Test.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import static org.testng.Assert.assertNotNull; public class Ticket3030Test extends SwaggerTestBase { private ModelResolver modelResolver; private ModelConverterContextImpl context; @BeforeTest public void setup() { modelResolver = new ModelResolver(new ObjectMapper()); context = new ModelConverterContextImpl(modelResolver); } @Test public void testTicket3030() throws Exception { final Schema model = context.resolve(new AnnotatedType(Child.class)); assertNotNull(model); String yaml = "Child:\n" + " type: object\n" + " allOf:\n" + " - $ref: \"#/components/schemas/Parent\"\n" + " - type: object\n" + " properties:\n" + " property:\n" + " type: string\n" + "Parent:\n" + " type: object\n" + " properties:\n" + " sharedProperty:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), yaml); } @io.swagger.v3.oas.annotations.media.Schema(subTypes = {Child.class}) static class Parent { public String sharedProperty; } @io.swagger.v3.oas.annotations.media.Schema(allOf = Parent.class) static class Child extends Parent { public String property; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3063Test.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import static org.testng.Assert.assertNotNull; public class Ticket3063Test extends SwaggerTestBase { private ModelResolver modelResolver; private ModelConverterContextImpl context; @BeforeTest public void setup() { modelResolver = new ModelResolver(new ObjectMapper()); context = new ModelConverterContextImpl(modelResolver); } @Test public void testTicket3063() throws Exception { final Schema model = context.resolve(new AnnotatedType(BaseClass.class)); assertNotNull(model); String yaml = "BaseClass:\n" + " required:\n" + " - type\n" + " type: object\n" + " properties:\n" + " type:\n" + " type: string\n" + " description: Type\n" + " example: AndroidDeviceRequirements\n" + " description: test\n" + " discriminator:\n" + " propertyName: type\n" + "SubClass:\n" + " required:\n" + " - type\n" + " type: object\n" + " description: SubClass\n" + " allOf:\n" + " - $ref: \"#/components/schemas/BaseClass\"\n" + " - type: object\n" + " properties:\n" + " additionalPropertyWhichShouldBeThere:\n" + " type: integer\n" + " description: Test\n" + " format: int32"; SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), yaml); } @io.swagger.v3.oas.annotations.media.Schema(description = "SubClass") public class SubClass extends BaseClass { @io.swagger.v3.oas.annotations.media.Schema(required = false, description = "Test") public int additionalPropertyWhichShouldBeThere = -1; } @io.swagger.v3.oas.annotations.media.Schema(description = "test", discriminatorProperty="type") @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = SubClass.class, name = "SubClass") }) public class BaseClass { @io.swagger.v3.oas.annotations.media.Schema(required = true, description = "Type", example="AndroidDeviceRequirements") public String type; public BaseClass(String type) { this.type = type; } public BaseClass() { } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3197Test.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import static org.testng.Assert.assertNotNull; public class Ticket3197Test extends SwaggerTestBase { private ModelResolver modelResolver; private ModelConverterContextImpl context; @BeforeMethod public void beforeMethod() { ModelResolver.composedModelPropertiesAsSibling = false; modelResolver = new ModelResolver(new ObjectMapper()); context = new ModelConverterContextImpl(modelResolver); } @AfterTest public void afterTest() { ModelResolver.composedModelPropertiesAsSibling = false; } @Test public void testTicket3197() throws Exception { final Schema model = context.resolve(new AnnotatedType(Car.class)); assertNotNull(model); String yaml = "Car:\n" + " required:\n" + " - type\n" + " type: object\n" + " properties:\n" + " carMetaData:\n" + " type: string\n" + " type:\n" + " type: string\n" + " discriminator:\n" + " propertyName: type\n" + " mapping:\n" + " RaceCar: \"#/components/schemas/RaceCar\"\n" + " SportCar: \"#/components/schemas/SportCar\"\n" + " oneOf:\n" + " - $ref: \"#/components/schemas/RaceCar\"\n" + " - $ref: \"#/components/schemas/SportCar\"\n" + "RaceCar:\n" + " required:\n" + " - carMetaData\n" + " - id\n" + " type: object\n" + " allOf:\n" + " - $ref: \"#/components/schemas/Car\"\n" + " - type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " model:\n" + " type: string\n" + "SportCar:\n" + " required:\n" + " - id\n" + " type: object\n" + " allOf:\n" + " - $ref: \"#/components/schemas/Car\"\n" + " - type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " model:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), yaml); } @Test public void testTicket3197AsSibling() throws Exception { ModelResolver.composedModelPropertiesAsSibling = true; ModelResolver myModelResolver = new ModelResolver(new ObjectMapper()); ModelResolver.composedModelPropertiesAsSibling = true; ModelConverterContextImpl myContext = new ModelConverterContextImpl(myModelResolver); final Schema model = myContext.resolve(new AnnotatedType(Car.class)); assertNotNull(model); String yaml = "Car:\n" + " required:\n" + " - type\n" + " type: object\n" + " properties:\n" + " carMetaData:\n" + " type: string\n" + " type:\n" + " type: string\n" + " discriminator:\n" + " propertyName: type\n" + " mapping:\n" + " RaceCar: \"#/components/schemas/RaceCar\"\n" + " SportCar: \"#/components/schemas/SportCar\"\n" + " oneOf:\n" + " - $ref: \"#/components/schemas/RaceCar\"\n" + " - $ref: \"#/components/schemas/SportCar\"\n" + "RaceCar:\n" + " required:\n" + " - carMetaData\n" + " - id\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " model:\n" + " type: string\n" + " allOf:\n" + " - $ref: \"#/components/schemas/Car\"\n" + "SportCar:\n" + " required:\n" + " - id\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " model:\n" + " type: string\n" + " allOf:\n" + " - $ref: \"#/components/schemas/Car\"\n"; SerializationMatchers.assertEqualsToYaml(myContext.getDefinedModels(), yaml); ModelResolver.composedModelPropertiesAsSibling = false; } @io.swagger.v3.oas.annotations.media.Schema(discriminatorProperty = "type", discriminatorMapping = { @DiscriminatorMapping(value = "RaceCar", schema = RaceCar.class), @DiscriminatorMapping(value = "SportCar", schema = SportCar.class) }, oneOf = { RaceCar.class, SportCar.class }) @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = RaceCar.class), @JsonSubTypes.Type(value = SportCar.class) }) static abstract class Car { private String carMetaData; public String getCarMetaData() { return carMetaData; } } static class RaceCar extends Car { @JsonProperty(required = true) public Long id; public String model; @io.swagger.v3.oas.annotations.media.Schema(required = true) public String carMetaData; } static class SportCar extends Car { @JsonProperty(required = true) public Long id; public String model; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3348Test.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.databind.ObjectMapper; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Map; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.models.media.Schema; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class Ticket3348Test extends SwaggerTestBase { private ModelResolver modelResolver; private ModelConverterContextImpl context; @BeforeMethod public void beforeMethod() { modelResolver = new ModelResolver(new ObjectMapper()); context = new ModelConverterContextImpl(modelResolver); } @Test public void testTicket3348() { final Schema model = context.resolve(new AnnotatedType(WithObjects.class)); assertNotNull(model); final Map props = model.getProperties(); assertEquals(props.size(), 2); } static class WithObjects { public Object param1; public Object param2; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3365Test.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import static org.testng.Assert.assertNotNull; public class Ticket3365Test extends SwaggerTestBase { private ModelResolver modelResolver; private ModelConverterContextImpl context; @BeforeMethod public void beforeMethod() { modelResolver = new ModelResolver(new ObjectMapper()); context = new ModelConverterContextImpl(modelResolver); } @Test public void testTicket3365() { Schema model = context.resolve(new AnnotatedType(ExampleWithJson.class)); assertNotNull(model); SerializationMatchers.assertEqualsToYaml(model, "required:\n" + "- param1\n" + "type: object\n" + "properties:\n" + " param1:\n" + " title: Cron formatted invoice schedule\n" + " type: object\n" + " example:\n" + " type: array\n" + " items:\n" + " type: string\n" + " format: byte"); model = context.resolve(new AnnotatedType(ExampleStartingWithInteger.class)); assertNotNull(model); SerializationMatchers.assertEqualsToYaml(model, "required:\n" + "- param1\n" + "type: object\n" + "properties:\n" + " param1:\n" + " title: Cron formatted invoice schedule\n" + " type: string\n" + " example: 0 0 5 * *\n"); } static class ExampleStartingWithInteger { @io.swagger.v3.oas.annotations.media.Schema( required = true, title = "Cron formatted invoice schedule", example = "0 0 5 * *" ) public String param1; } static class ExampleWithJson { @io.swagger.v3.oas.annotations.media.Schema( required = true, title = "Cron formatted invoice schedule", example = "{\"type\": \"array\", \"items\": {\"type\" : \"string\", \"format\": \"byte\"}}" ) public Object param1; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3624Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Optional; public class Ticket3624Test extends SwaggerTestBase { @Test public void testSelfReferencingOptional() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(ModelContainer.class)); Yaml.prettyPrint(context.getDefinedModels()); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "Model:\n" + " type: object\n" + " properties:\n" + " model:\n" + " $ref: \"#/components/schemas/Model\"\n" + "ModelContainer:\n" + " type: object\n" + " properties:\n" + " model:\n" + " $ref: \"#/components/schemas/Model\"\n"); } static class ModelContainer { public Optional model; } static class Model { public Optional model; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3697Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.TestObject3697; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class Ticket3697Test extends SwaggerTestBase { @Test public void testHiddenJsonCreator() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(TestObject3697.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "TestObject3697:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3699Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.TestObject3699; import org.testng.annotations.Test; public class Ticket3699Test extends SwaggerTestBase { @Test public void test3699() { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); context.resolve(new AnnotatedType(TestObject3699.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "TestObject3699:\n" + " type: object\n" + " properties:\n" + " CustomName:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " foo:\n" + " type: array\n" + " items:\n" + " type: string\n"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3703Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Optional; public class Ticket3703Test extends SwaggerTestBase { @Test public void testSelfReferencingOptional() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(ModelContainer.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "Model:\n" + " type: object\n" + " properties:\n" + " model:\n" + " $ref: \"#/components/schemas/Model\"\n" + "ModelContainer:\n" + " type: object\n" + " properties:\n" + " model:\n" + " $ref: \"#/components/schemas/Model\"\n" + " bytes:\n" + " type: string\n" + " format: byte"); } static class ModelContainer { public Optional model; @io.swagger.v3.oas.annotations.media.Schema(type = "string", format = "byte") public Optional getBytes() { return null; } } static class Model { public Optional model; } static class Bytes { public String foo; public String bar; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3853Test.java ================================================ package io.swagger.v3.core.resolving; import static org.testng.Assert.assertNotNull; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.jackson.TypeNameResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class Ticket3853Test extends SwaggerTestBase { private ModelResolver modelResolver; private ModelConverterContextImpl context; @BeforeTest public void setup() { modelResolver = new ModelResolver(new ObjectMapper(), new FqnTypeNameResolver()); context = new ModelConverterContextImpl(modelResolver); } @Test public void testTicket3853() { final Schema model = context.resolve(new AnnotatedType(BaseClass.class)); assertNotNull(model); String yaml = "io.swagger.v3.core.resolving.Ticket3853Test$BaseClass:\n" + " type: object\n" + " properties:\n" + " property:\n" + " type: string\n" + " type:\n" + " type: string\n" + "io.swagger.v3.core.resolving.Ticket3853Test$SubClass:\n" + " type: object\n" + " allOf:\n" + " - $ref: \"#/components/schemas/io.swagger.v3.core.resolving.Ticket3853Test$BaseClass\"\n" + " - type: object\n" + " properties:\n" + " subClassProperty:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), yaml); } static class SubClass extends BaseClass { public String subClassProperty; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME) @JsonSubTypes({ @JsonSubTypes.Type(value = SubClass.class, name = "SubClass"), @JsonSubTypes.Type(value = BaseClass.class, name = "BaseClass"), }) static class BaseClass { public String property; public String type; } static class FqnTypeNameResolver extends TypeNameResolver { @Override protected String getNameOfClass(Class cls) { return cls.getName(); } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket3904Test.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class Ticket3904Test extends SwaggerTestBase { @Test public void testJsonValueSchemaAnnotation() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(Request.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "Request:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " description: Description of ID."); } static class Request { @io.swagger.v3.oas.annotations.media.Schema(description = "Description of ID.") private Id id; public Id getId() { return id; } public void setId(Id id) { this.id = id; } } static class Id { private String value; @JsonValue public String getValue() { return value; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4239Test.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonView; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import org.testng.annotations.Test; import java.lang.annotation.Annotation; import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME; public class Ticket4239Test extends SwaggerTestBase { public interface Input {} public interface Output {} @JsonTypeInfo(use = NAME) @JsonSubTypes({ @JsonSubTypes.Type(value = A1.class), }) public static abstract class A { @JsonView(Input.class) public String a_in; @JsonView(Output.class) public String a_out; } public static class A1 extends A { @JsonView(Input.class) public String a1_in; @JsonView(Output.class) public String a1_out; } private static final JsonView VIEW_OUTPUT = new JsonView() { public Class annotationType() { return JsonView.class; } public Class[] value() { return new Class[] {Output.class}; } }; @Test public void testJsonValueSchemaAnnotation() { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); AnnotatedType type = new AnnotatedType(Ticket4239Test.A.class).jsonViewAnnotation(VIEW_OUTPUT); context.resolve(type); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "A1_Output:\n" + " type: object\n" + " allOf:\n" + " - $ref: \"#/components/schemas/A_Output\"\n" + " - type: object\n" + " properties:\n" + " a1_out:\n" + " type: string\n" + "A_Output:\n" + " type: object\n" + " properties:\n" + " a_out:\n" + " type: string\n"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4290Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.resources.Issue4290; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class Ticket4290Test extends SwaggerTestBase { @Test public void testAnyOf() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(Issue4290.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "Issue4290:\n" + " type: object\n" + " properties:\n" + " value:\n" + " type: object\n" + " description: \"A string, a number or a boolean\"\n" + " anyOf:\n" + " - type: string\n" + " - type: number\n" + " - type: boolean"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4362Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import java.time.DayOfWeek; public class Ticket4362Test extends SwaggerTestBase { @AfterMethod public void afterTest() { ModelResolver.enumsAsRef = false; } @Test public void testAnyOf() throws Exception { ModelResolver.enumsAsRef = true; final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(DayOfWeek.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "DayOfWeek:\n" + " type: string\n" + " enum:\n" + " - MONDAY\n" + " - TUESDAY\n" + " - WEDNESDAY\n" + " - THURSDAY\n" + " - FRIDAY\n" + " - SATURDAY\n" + " - SUNDAY"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4474Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Ticket4474Test extends SwaggerTestBase { @AfterMethod public void afterTest() { ModelResolver.enumsAsRef = false; } @Test public void testAnyOf() throws Exception { ModelResolver.enumsAsRef = true; final ModelResolver modelResolver = new ModelResolver(mapper()); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); final Schema model = context .resolve(new AnnotatedType(Document.class)); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "Document:\n" + " type: object\n" + " properties:\n" + " data:\n" + " type: object\n" + " additionalProperties:\n" + " type: object\n" + " anyOf:\n" + " - type: array\n" + " items:\n" + " type: boolean\n" + " - type: array\n" + " items:\n" + " type: integer\n" + " format: int32\n" + " - type: array\n" + " items:\n" + " type: integer\n" + " format: int64\n" + " - type: array\n" + " items:\n" + " type: number\n" + " format: double\n" + " - type: array\n" + " items:\n" + " type: string\n" + " - type: boolean\n" + " - type: integer\n" + " format: int32\n" + " - type: integer\n" + " format: int64\n" + " listData:\n" + " type: array\n" + " items:\n" + " type: object\n" + " anyOf:\n" + " - type: array\n" + " items:\n" + " type: boolean\n" + " - type: array\n" + " items:\n" + " type: integer\n" + " format: int32\n" + " - type: array\n" + " items:\n" + " type: integer\n" + " format: int64\n" + " - type: array\n" + " items:\n" + " type: number\n" + " format: double\n" + " - type: array\n" + " items:\n" + " type: string\n" + " - type: boolean\n" + " - type: integer\n" + " format: int32\n" + " - type: integer\n" + " format: int64\n" + " itemData:\n" + " type: object\n" + " anyOf:\n" + " - type: array\n" + " items:\n" + " type: boolean\n" + " - type: array\n" + " items:\n" + " type: integer\n" + " format: int32\n" + " - type: array\n" + " items:\n" + " type: integer\n" + " format: int64\n" + " - type: array\n" + " items:\n" + " type: number\n" + " format: double\n" + " - type: array\n" + " items:\n" + " type: string\n" + " - type: boolean\n" + " - type: integer\n" + " format: int32\n" + " - type: integer\n" + " format: int64"); } static class Document { @io.swagger.v3.oas.annotations.media.Schema( anyOf = { Boolean[].class, Integer[].class, Long[].class, Double[].class, String[].class, Boolean.class, Integer.class, Long.class, Map.class, }) public Map data = new HashMap<>(); @io.swagger.v3.oas.annotations.media.Schema( anyOf = { Boolean[].class, Integer[].class, Long[].class, Double[].class, String[].class, Boolean.class, Integer.class, Long.class, Map.class, }) public List listData = new ArrayList<>(); @io.swagger.v3.oas.annotations.media.Schema( anyOf = { Boolean[].class, Integer[].class, Long[].class, Double[].class, String[].class, Boolean.class, Integer.class, Long.class, Map.class, }) public Object itemData = new Object(); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4679Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.annotations.media.Schema; import org.testng.annotations.Test; import java.util.Map; public class Ticket4679Test extends SwaggerTestBase{ @Test(description = "Custom schema implementation in property overrides type value") public void testCustomSchemaImplementation() { String expectedYaml = "ModelWithCustomSchemaImplementationInProperty:\n" + " type: object\n" + " properties:\n" + " exampleField:\n" + " type: integer\n" + " format: int32\n" + " secondExampleField:\n" + " type: string\n"; Map stringSchemaMap = ModelConverters.getInstance(true).readAll(ModelWithCustomSchemaImplementationInProperty.class); SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); } static class ModelWithCustomSchemaImplementationInProperty { @Schema(implementation = Integer.class) private String exampleField; @Schema(type = "string") private Integer secondExampleField; public String getExampleField() { return exampleField; } public void setExampleField(String exampleField) { this.exampleField = exampleField; } public Integer getSecondExampleField() { return secondExampleField; } public void setSecondExampleField(Integer secondExampleField) { this.secondExampleField = secondExampleField; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4760Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import javax.validation.constraints.Size; import java.util.List; import java.util.Map; public class Ticket4760Test { @Test public void testArraySchemaItemsValidation(){ final Map stringSchemaMap = ModelConverters.getInstance().readAll(ClassWithArraySchemaItemsValidation.class); final String expectedJson = "{\n" + " \"ClassWithArraySchemaItemsValidation\" : {\n" + " \"type\" : \"object\",\n" + " \"properties\" : {\n" + " \"setOfEnums\" : {\n" + " \"maxItems\" : 3,\n" + " \"minItems\" : 1,\n" + " \"type\" : \"array\",\n" + " \"items\" : {\n" + " \"type\" : \"string\",\n" + " \"enum\" : [ \"green\", \"blue\" ]\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(stringSchemaMap, expectedJson); } private static class ClassWithArraySchemaItemsValidation{ public enum MyEnum { red, green } public enum MyOtherEnum { green, blue } @io.swagger.v3.oas.annotations.media.ArraySchema(schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = MyOtherEnum.class)) @Size(min = 1, max = 3) private List setOfEnums; public List getSetOfEnums() { return setOfEnums; } public void setSetOfEnums(List setOfEnums) { this.setOfEnums = setOfEnums; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4771Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class Ticket4771Test { @Test public void testArraySchemaItemsValidation(){ ModelConverters.reset(); System.clearProperty(Schema.APPLY_SCHEMA_RESOLUTION_PROPERTY); ResolvedSchema schema = ModelConverters.getInstance(false, Schema.SchemaResolution.INLINE).resolveAsResolvedSchema(new AnnotatedType().type(CustomClass[].class)); String expectedJson = "{\n" + " \"schema\" : {\n" + " \"type\" : \"array\",\n" + " \"items\" : {\n" + " \"type\" : \"object\",\n" + " \"properties\" : {\n" + " \"foo\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"referencedSchemas\" : {\n" + " \"CustomClass\" : {\n" + " \"type\" : \"object\",\n" + " \"properties\" : {\n" + " \"foo\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(schema, expectedJson); ModelConverters.reset(); schema = ModelConverters.getInstance(true, Schema.SchemaResolution.INLINE).resolveAsResolvedSchema(new AnnotatedType().type(CustomClass[].class)); expectedJson = "{\n" + " \"schema\" : {\n" + " \"type\" : \"array\",\n" + " \"items\" : {\n" + " \"$ref\" : \"#/components/schemas/CustomClass\"\n" + " }\n" + " },\n" + " \"referencedSchemas\" : {\n" + " \"CustomClass\" : {\n" + " \"type\" : \"object\",\n" + " \"properties\" : {\n" + " \"foo\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson31(schema, expectedJson); ModelConverters.reset(); System.setProperty(Schema.APPLY_SCHEMA_RESOLUTION_PROPERTY, "true"); schema = ModelConverters.getInstance(true, Schema.SchemaResolution.INLINE).resolveAsResolvedSchema(new AnnotatedType().type(CustomClass[].class)); expectedJson = "{\n" + " \"schema\" : {\n" + " \"type\" : \"array\",\n" + " \"items\" : {\n" + " \"type\" : \"object\",\n" + " \"properties\" : {\n" + " \"foo\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"referencedSchemas\" : {\n" + " \"CustomClass\" : {\n" + " \"type\" : \"object\",\n" + " \"properties\" : {\n" + " \"foo\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson31(schema, expectedJson); System.clearProperty(Schema.APPLY_SCHEMA_RESOLUTION_PROPERTY); ModelConverters.reset(); } private static class CustomClass { public String foo; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4800Test.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import java.util.Map; public class Ticket4800Test extends SwaggerTestBase{ @Test(description = "Custom schema implementation in property and enum as ref type value") public void testCustomSchemaImplementation() { String expectedYaml = "ModelWithCustomSchemaImplementationInProperty:\n" + " type: object\n" + " properties:\n" + " enumExampleFieldWithImplementationProp:\n" + " $ref: \"#/components/schemas/MyEnum\"\n" + " default: \"yes\"\n" + " description: Prop description\n" + " secondExampleFieldWithTypeProp:\n" + " type: string\n" + "MyEnum:\n" + " type: string\n" + " enum:\n" + " - \"yes\"\n" + " - \"no\""; Map stringSchemaMap = ModelConverters.getInstance(true).readAll(Ticket4800Test.ModelWithCustomSchemaImplementationInProperty.class); SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); } static class ModelWithCustomSchemaImplementationInProperty { @io.swagger.v3.oas.annotations.media.Schema(implementation = MyEnum.class, description = "Prop description", defaultValue = "yes", enumAsRef = true) private MyEnum enumExampleFieldWithImplementationProp; @io.swagger.v3.oas.annotations.media.Schema(type = "string", enumAsRef = true) private MyEnum2 secondExampleFieldWithTypeProp; public MyEnum getEnumExampleFieldWithImplementationProp() { return enumExampleFieldWithImplementationProp; } public void setEnumExampleFieldWithImplementationProp(MyEnum enumExampleFieldWithImplementationProp) { this.enumExampleFieldWithImplementationProp = enumExampleFieldWithImplementationProp; } public MyEnum2 getSecondExampleFieldWithTypeProp() { return secondExampleFieldWithTypeProp; } public void setSecondExampleFieldWithTypeProp(MyEnum2 secondExampleFieldWithTypeProp) { this.secondExampleFieldWithTypeProp = secondExampleFieldWithTypeProp; } enum MyEnum { yes, no } //Should not be included in the model definitions enum MyEnum2 { si, no } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/Ticket4904Test.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.models.media.ComposedSchema; import io.swagger.v3.oas.models.media.JsonSchema; import org.testng.annotations.Test; import static io.swagger.v3.core.resolving.SwaggerTestBase.mapper; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class Ticket4904Test { @Test public void testComposedSchemaWithDiscriminator() { final ModelResolver modelResolver = new ModelResolver(mapper()); modelResolver.setOpenapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema schema = context.resolve(new AnnotatedType(ParentClass.class)); assertNotNull(schema); assertTrue(schema instanceof JsonSchema, "Expected JsonSchema in OpenAPI 3.1 mode, but got: " + schema.getClass()); JsonSchema jsonSchema = (JsonSchema) schema; assertNotNull(jsonSchema.getOneOf()); assertEquals(jsonSchema.getOneOf().size(), 2); assertEquals(( jsonSchema.getOneOf().get(0)).get$ref(), "#/components/schemas/ChildClassA"); assertEquals(( jsonSchema.getOneOf().get(1)).get$ref(), "#/components/schemas/ChildClassB"); assertNotNull(jsonSchema.getDiscriminator()); assertEquals(jsonSchema.getDiscriminator().getPropertyName(), "objectType"); assertNotNull(jsonSchema.getDiscriminator().getMapping()); assertEquals(jsonSchema.getDiscriminator().getMapping().size(), 2); assertEquals(jsonSchema.getDiscriminator().getMapping().get("A"), "#/components/schemas/ChildClassA"); assertEquals(jsonSchema.getDiscriminator().getMapping().get("B"), "#/components/schemas/ChildClassB"); } @Test public void testMultiElementAllOf() { final ModelResolver modelResolver = new ModelResolver(mapper()); modelResolver.setOpenapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema schema = context.resolve(new AnnotatedType(MultiAllOfClass.class)); assertNotNull(schema); assertTrue(schema instanceof JsonSchema, "Expected JsonSchema in OpenAPI 3.1 mode, but got: " + schema.getClass()); assertNotNull(schema.getAllOf()); assertEquals(schema.getAllOf().size(), 3); assertEquals(((io.swagger.v3.oas.models.media.Schema) schema.getAllOf().get(0)).get$ref(), "#/components/schemas/ClassA"); assertEquals(((io.swagger.v3.oas.models.media.Schema) schema.getAllOf().get(1)).get$ref(), "#/components/schemas/ClassB"); assertEquals(((io.swagger.v3.oas.models.media.Schema) schema.getAllOf().get(2)).get$ref(), "#/components/schemas/ClassC"); } @Test public void testMultiElementAllOfOpenApi30() { final ModelResolver modelResolver = new ModelResolver(mapper()); modelResolver.setOpenapi31(false); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema schema = context.resolve(new AnnotatedType(MultiAllOfClass.class)); assertNotNull(schema); assertTrue(schema instanceof ComposedSchema, "Expected ComposedSchema in OpenAPI 3.0 mode, but got: " + schema.getClass()); ComposedSchema composedSchema = (ComposedSchema) schema; assertNotNull(composedSchema.getAllOf()); assertEquals(composedSchema.getAllOf().size(), 3); assertEquals(composedSchema.getAllOf().get(0).get$ref(), "#/components/schemas/ClassA"); assertEquals(composedSchema.getAllOf().get(1).get$ref(), "#/components/schemas/ClassB"); assertEquals(composedSchema.getAllOf().get(2).get$ref(), "#/components/schemas/ClassC"); } @Test public void testMixedComposition() { final ModelResolver modelResolver = new ModelResolver(mapper()); modelResolver.setOpenapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema schema = context.resolve(new AnnotatedType(MixedCompositionClass.class)); assertNotNull(schema); assertTrue(schema instanceof JsonSchema, "Expected JsonSchema in OpenAPI 3.1 mode, but got: " + schema.getClass()); JsonSchema jsonSchema = (JsonSchema) schema; assertNotNull(jsonSchema.getAllOf()); assertEquals(jsonSchema.getAllOf().size(), 3); assertEquals(jsonSchema.getAllOf().get(0).get$ref(), "#/components/schemas/ClassA"); assertEquals(jsonSchema.getAllOf().get(1).get$ref(), "#/components/schemas/ClassB"); io.swagger.v3.oas.models.media.Schema inlineSchema = jsonSchema.getAllOf().get(2); assertNotNull(inlineSchema); assertEquals(inlineSchema.get$ref(), null); assertNotNull(inlineSchema.getProperties()); assertTrue(inlineSchema.getProperties().containsKey("additionalProperty")); io.swagger.v3.oas.models.media.Schema additionalPropertySchema = (io.swagger.v3.oas.models.media.Schema) inlineSchema.getProperties().get("additionalProperty"); assertNotNull(additionalPropertySchema); assertEquals(additionalPropertySchema.getDescription(), "Additional property"); } @Test public void testAnyOfComposition() { final ModelResolver modelResolver = new ModelResolver(mapper()); modelResolver.setOpenapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema schema = context.resolve(new AnnotatedType(AnyOfClass.class)); assertNotNull(schema); assertTrue(schema instanceof JsonSchema, "Expected JsonSchema in OpenAPI 3.1 mode, but got: " + schema.getClass()); JsonSchema jsonSchema = (JsonSchema) schema; assertNotNull(jsonSchema.getAnyOf()); assertEquals(jsonSchema.getAnyOf().size(), 3); assertEquals(((io.swagger.v3.oas.models.media.Schema) jsonSchema.getAnyOf().get(0)).get$ref(), "#/components/schemas/ClassA"); assertEquals(((io.swagger.v3.oas.models.media.Schema) jsonSchema.getAnyOf().get(1)).get$ref(), "#/components/schemas/ClassB"); assertEquals(((io.swagger.v3.oas.models.media.Schema) jsonSchema.getAnyOf().get(2)).get$ref(), "#/components/schemas/ClassC"); } @Test public void testOneOfWithReferences() { final ModelResolver modelResolver = new ModelResolver(mapper()); modelResolver.setOpenapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema schema = context.resolve(new AnnotatedType(OneOfWithRefsClass.class)); assertNotNull(schema); assertTrue(schema instanceof JsonSchema, "Expected JsonSchema in OpenAPI 3.1 mode, but got: " + schema.getClass()); JsonSchema jsonSchema = (JsonSchema) schema; assertNotNull(jsonSchema.getOneOf()); assertEquals(jsonSchema.getOneOf().size(), 2); assertEquals((jsonSchema.getOneOf().get(0)).get$ref(), "#/components/schemas/RefSubtypeA"); assertEquals((jsonSchema.getOneOf().get(1)).get$ref(), "#/components/schemas/RefSubtypeB"); } @Test public void testJacksonPolymorphismWithTypeInfo() { final ModelResolver modelResolver = new ModelResolver(mapper()); modelResolver.setOpenapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema schema = context.resolve(new AnnotatedType(JacksonPolymorphicParent.class)); assertNotNull(schema); assertTrue(schema instanceof JsonSchema, "Expected JsonSchema in OpenAPI 3.1 mode, but got: " + schema.getClass()); JsonSchema jsonSchema = (JsonSchema) schema; if (jsonSchema.getOneOf() != null) { assertEquals(jsonSchema.getOneOf().size(), 2); assertEquals((jsonSchema.getOneOf().get(0)).get$ref(), "#/components/schemas/JacksonChildA"); assertEquals((jsonSchema.getOneOf().get(1)).get$ref(), "#/components/schemas/JacksonChildB"); assertNotNull(jsonSchema.getDiscriminator()); assertEquals(jsonSchema.getDiscriminator().getPropertyName(), "type"); } else { assertNotNull(jsonSchema.getProperties()); assertTrue(jsonSchema.getProperties().containsKey("commonProperty") || jsonSchema.getProperties().containsKey("type"), "Expected to find either commonProperty or type discriminator property"); } } @Test public void testComplexAllOfWithInlineProperties() { final ModelResolver modelResolver = new ModelResolver(mapper()); modelResolver.setOpenapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema schema = context.resolve(new AnnotatedType(ComplexAllOfClass.class)); assertNotNull(schema); assertTrue(schema instanceof JsonSchema, "Expected JsonSchema in OpenAPI 3.1 mode, but got: " + schema.getClass()); JsonSchema jsonSchema = (JsonSchema) schema; assertNotNull(jsonSchema.getAllOf()); assertEquals(jsonSchema.getAllOf().size(), 3); assertEquals((jsonSchema.getAllOf().get(0)).get$ref(), "#/components/schemas/ClassA"); assertEquals((jsonSchema.getAllOf().get(1)).get$ref(), "#/components/schemas/ClassB"); io.swagger.v3.oas.models.media.Schema inlineSchema = jsonSchema.getAllOf().get(2); assertNotNull(inlineSchema); assertEquals(inlineSchema.get$ref(), null); assertNotNull(inlineSchema.getProperties()); assertTrue(inlineSchema.getProperties().containsKey("complexProperty")); assertTrue(inlineSchema.getProperties().containsKey("additionalField")); } @Test public void testNestedComposition() { final ModelResolver modelResolver = new ModelResolver(mapper()); modelResolver.setOpenapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema schema = context.resolve(new AnnotatedType(NestedCompositionClass.class)); assertNotNull(schema); assertTrue(schema instanceof JsonSchema, "Expected JsonSchema in OpenAPI 3.1 mode, but got: " + schema.getClass()); JsonSchema jsonSchema = (JsonSchema) schema; assertNotNull(jsonSchema.getOneOf()); assertNotNull(jsonSchema.getAllOf()); assertEquals(jsonSchema.getOneOf().size(), 2); assertEquals(jsonSchema.getAllOf().size(), 1); assertEquals((jsonSchema.getOneOf().get(0)).get$ref(), "#/components/schemas/ChildClassA"); assertEquals((jsonSchema.getOneOf().get(1)).get$ref(), "#/components/schemas/ChildClassB"); assertEquals((jsonSchema.getAllOf().get(0)).get$ref(), "#/components/schemas/ClassA"); } @Schema( type = "object", discriminatorMapping = { @DiscriminatorMapping(value = "A", schema = ChildClassA.class), @DiscriminatorMapping(value = "B", schema = ChildClassB.class) }, oneOf = {ChildClassA.class, ChildClassB.class}, discriminatorProperty = "objectType" ) public abstract static class ParentClass { } public static class ChildClassA extends ParentClass { } public static class ChildClassB extends ParentClass { } @Schema(allOf = {ClassA.class, ClassB.class, ClassC.class}) public static class MultiAllOfClass { } @Schema( allOf = {ClassA.class, ClassB.class}, type = "object", description = "Mixed composition with allOf and additional properties", format = "custom-format" ) public static class MixedCompositionClass { @Schema(description = "Additional property") public String additionalProperty; } public static class ClassA { public String propertyA; } public static class ClassB { public String propertyB; } public static class ClassC { public String propertyC; } @Schema(anyOf = {ClassA.class, ClassB.class, ClassC.class}) public static class AnyOfClass { } @Schema(oneOf = {RefSubtypeA.class, RefSubtypeB.class}) public static class OneOfWithRefsClass { } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = JacksonChildA.class, name = "A"), @JsonSubTypes.Type(value = JacksonChildB.class, name = "B") }) public static class JacksonPolymorphicParent { public String commonProperty; } public static class JacksonChildA extends JacksonPolymorphicParent { public String childAProperty; } public static class JacksonChildB extends JacksonPolymorphicParent { public String childBProperty; } @Schema(allOf = {ClassA.class, ClassB.class}) public static class ComplexAllOfClass { @Schema(description = "Complex property with nested structure") public String complexProperty; @Schema(description = "Additional field for testing") public String additionalField; } @Schema( oneOf = {ChildClassA.class, ChildClassB.class}, allOf = {ClassA.class} ) public static class NestedCompositionClass { } // Additional classes for $ref subtypes testing public static class RefSubtypeA { public String refPropertyA; } public static class RefSubtypeB { public String refPropertyB; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/XMLGregorianCalendarTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import javax.xml.datatype.XMLGregorianCalendar; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class XMLGregorianCalendarTest { @Test(description = "it should read a model with XMLGregorianCalendar") public void testXMLGregorianCalendar() { final Map models = ModelConverters.getInstance().readAll(ModelWithCalendar.class); assertEquals(models.size(), 1); // don't create a Joda DateTime object Schema model = models.get("ModelWithCalendar"); final Map properties = model.getProperties(); final Schema nameProperty = properties.get("name"); assertTrue(nameProperty instanceof StringSchema); assertEquals(nameProperty.getDescription(), "name of the model"); final Schema dateTimeSchema = properties.get("createdAt"); assertTrue(dateTimeSchema instanceof DateTimeSchema); assertTrue(model.getRequired().contains("createdAt")); assertEquals(dateTimeSchema.getDescription(), "creation timestamp"); } class ModelWithCalendar { @io.swagger.v3.oas.annotations.media.Schema(description = "name of the model") public String name; @io.swagger.v3.oas.annotations.media.Schema(description = "creation timestamp", required = true) public XMLGregorianCalendar createdAt; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/XMLInfoTest.java ================================================ package io.swagger.v3.core.resolving; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.XML; import org.testng.annotations.Test; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlElementRefs; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.util.List; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class XMLInfoTest extends SwaggerTestBase { @Test public void testSimple() throws Exception { final ModelConverter mr = modelResolver(); ModelConverterContextImpl ctx = new ModelConverterContextImpl(mr); final Schema model = mr.resolve(new AnnotatedType(XmlDecoratedBean.class), ctx, null); final XML xml = model.getXml(); assertNotNull(xml); assertEquals(xml.getName(), "xmlDecoratedBean"); // Cast it to an array property final ArraySchema property = (ArraySchema) model.getProperties().get("elements"); assertNotNull(property); final XML propertyXml = property.getXml(); assertNotNull(propertyXml); assertNull(propertyXml.getName()); assertTrue(propertyXml.getWrapped()); // Get the xml for items for the array property final XML itemsXml = property.getItems().getXml(); assertNotNull(itemsXml); // Check the name of item name assertEquals(itemsXml.getName(), "element"); assertNotNull(model.getProperties().get("elementC")); } @XmlRootElement(name = "xmlDecoratedBean") @io.swagger.v3.oas.annotations.media.Schema(description = "DESC") static class XmlDecoratedBean { @XmlElement(name = "elementB") public int b; @XmlElementWrapper(name = "elements") @XmlElement(name = "element") public List elements; @JsonProperty("elementC") public String c; } @Test public void testReadingXmlAccessorTypeNone() throws Exception { final ModelConverter mr = modelResolver(); final Schema model = mr.resolve(new AnnotatedType(XmlDecoratedBeanXmlAccessorNone.class), new ModelConverterContextImpl(mr), null); final XML xml = model.getXml(); assertNotNull(xml); assertEquals(xml.getName(), "xmlDecoratedBean"); final Schema property = (Schema) model.getProperties().get("a"); assertNotNull(property); assertNull(model.getProperties().get("b")); assertNotNull(model.getProperties().get("c")); assertNotNull(model.getProperties().get("d")); assertNotNull(model.getProperties().get("e")); assertNotNull(model.getProperties().get("f")); } @Test public void testReadingXmlAccessorTypePublic() throws Exception { final ModelConverter mr = modelResolver(); final Schema model = mr.resolve(new AnnotatedType(XmlDecoratedBeanXmlAccessorPublic.class), new ModelConverterContextImpl(mr), null); final XML xml = model.getXml(); assertNotNull(xml); assertEquals(xml.getName(), "xmlDecoratedBean"); final Schema propertyA = (Schema) model.getProperties().get("a"); assertNotNull(propertyA); final Schema propertyB = (Schema) model.getProperties().get("b"); assertNotNull(propertyB); final Schema propertyC = (Schema) model.getProperties().get("c"); assertNull(propertyC); } @XmlRootElement(name = "xmlDecoratedBean") @XmlAccessorType(XmlAccessType.NONE) @io.swagger.v3.oas.annotations.media.Schema static class XmlDecoratedBeanXmlAccessorNone { @XmlElement public int a; public String b; @XmlAttribute public String c; @XmlElementRef public XmlDecoratedBean d; @XmlElementRefs(value = {@XmlElementRef}) public List e; @JsonProperty public int f; } @XmlRootElement(name = "xmlDecoratedBean") @io.swagger.v3.oas.annotations.media.Schema static class XmlDecoratedBeanXmlAccessorPublic { @XmlElement public int a; public String b; @JsonIgnore public String c; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/XmlModelTest.java ================================================ package io.swagger.v3.core.resolving; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.oas.models.Address; import io.swagger.v3.core.oas.models.Issue534; import io.swagger.v3.core.oas.models.ModelWithJAXBAnnotations; import io.swagger.v3.core.oas.models.xmltest.NestedModelWithJAXBAnnotations; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.XML; import org.testng.annotations.Test; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; public class XmlModelTest { @Test(description = "it should process an XML model attribute") public void processXMLModelAttribute() { final Map schemas = ModelConverters.getInstance().readAll(Monster.class); final Schema model = schemas.get("Monster"); assertNotNull(model); assertTrue(model instanceof Schema); XML xml = model.getXml(); assertNotNull(xml); assertEquals(xml.getName(), "monster"); final Schema property = (Schema) model.getProperties().get("children"); assertNotNull(property); xml = property.getXml(); assertTrue(xml.getWrapped()); assertNull(xml.getName()); } @Test(description = "it should not create an xml object") public void itShouldNotCreateXmlObject() { final Map schemas = ModelConverters.getInstance().readAll(Address.class); final Schema model = schemas.get("Address"); assertNotNull(model); assertTrue(model instanceof Schema); final Schema property = (Schema) model.getProperties().get("streetNumber"); final XML xml = property.getXml(); assertNull(xml); } @Test(description = "it should stay hidden per 534") public void stayHidden() { final Map schemas = ModelConverters.getInstance().readAll(Issue534.class); assertEquals(schemas.get("Issue534").getProperties().size(), 1); } @Test(description = "it should process a model with JAXB annotations") public void processModelWithJAXBAnnotations() { final Map schemas = ModelConverters.getInstance().readAll(ModelWithJAXBAnnotations.class); assertEquals(schemas.size(), 1); final Schema model = schemas.get("ModelWithJAXBAnnotations"); assertNotNull(model); assertTrue(model instanceof Schema); final XML rootXml = model.getXml(); assertNotNull(rootXml); assertEquals(rootXml.getName(), "rootName"); Map props = model.getProperties(); for (Map.Entry entry : props.entrySet()) { final String name = entry.getKey(); final Schema property = entry.getValue(); if ("id".equals(name)) { final XML xml = property.getXml(); assertNotNull(xml); assertNull(xml.getName()); assertTrue(xml.getAttribute()); assertNull(xml.getWrapped()); } else if ("name".equals(name)) { final XML xml = property.getXml(); assertNotNull(xml); assertEquals(xml.getName(), "renamed"); assertNull(xml.getAttribute()); assertNull(xml.getWrapped()); } else if (Arrays.asList("list", "forcedElement").contains(name)) { assertNull(property.getXml()); } else if ("wrappedList".equals(name)) { final XML xml = property.getXml(); assertNotNull(xml); assertEquals(xml.getName(), "wrappedListItems"); assertNull(xml.getAttribute()); assertTrue(xml.getWrapped()); } else { fail(String.format("Unexpected property: %s", name)); } } } @Test(description = "it should process a nested model with JAXB annotations and a namespace") public void processModelWithJAXBAnnotationsAndNamespace() { final Map schemas = ModelConverters.getInstance().readAll(NestedModelWithJAXBAnnotations.class); assertEquals(schemas.size(), 2); final Schema model = schemas.get("NestedModelWithJAXBAnnotations"); assertNotNull(model); assertTrue(model instanceof Schema); final XML rootXml = model.getXml(); assertNotNull(rootXml); assertEquals(rootXml.getName(), "RootName"); assertEquals(rootXml.getNamespace(), "https://www.openapis.org/test/nested"); Map props = model.getProperties(); for (Map.Entry entry : props.entrySet()) { final String name = entry.getKey(); final Schema property = entry.getValue(); if ("id".equals(name)) { final XML xml = property.getXml(); assertNotNull(xml); assertNull(xml.getName()); assertTrue(xml.getAttribute()); assertNull(xml.getWrapped()); } else if ("name".equals(name)) { final XML xml = property.getXml(); assertNotNull(xml); assertEquals(xml.getName(), "named"); assertNull(xml.getAttribute()); assertNull(xml.getWrapped()); } else if ("subName".equals(name)) { final XML xml = property.getXml(); assertNotNull(xml); assertEquals(xml.getName(), "SubName"); assertNull(xml.getAttribute()); assertNull(xml.getWrapped()); } else { fail(String.format("Unexpected property: %s", name)); } } } @Test(description = "it should deserialize a model") public void deserializeModel() throws IOException { final String yaml = "---\n" + "type: \"object\"\n" + "properties:\n" + " id:\n" + " type: \"string\"\n" + " xml:\n" + " attribute: true\n" + " name:\n" + " type: \"string\"\n" + " xml:\n" + " name: \"renamed\"\n" + " list:\n" + " type: \"array\"\n" + " items:\n" + " type: \"string\"\n" + " wrappedList:\n" + " type: \"array\"\n" + " xml:\n" + " name: \"wrappedListItems\"\n" + " wrapped: true\n" + " items:\n" + " type: \"string\"\n" + " forcedElement:\n" + " type: \"array\"\n" + " items:\n" + " type: \"string\"\n" + "xml:\n" + " name: \"rootName\""; final Schema model = Yaml.mapper().readValue(yaml, Schema.class); final Schema wrappedList = (Schema) model.getProperties().get("wrappedList"); assertNotNull(wrappedList); assertNotNull(wrappedList.getXml()); assertEquals(wrappedList.getXml().getName(), "wrappedListItems"); } @XmlRootElement(name = "monster") class Monster { public String name = ""; @XmlElementWrapper() @XmlElement(name = "children") public java.util.List children = new ArrayList(); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/BidimensionalArray.java ================================================ package io.swagger.v3.core.resolving.resources; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.v3.oas.annotations.media.ArraySchema; import javax.validation.constraints.Size; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; public class BidimensionalArray { @ArraySchema(maxItems = 3) @MySizeAnnotation(maxItems = 2) public List> withCustomAnnotation; @ArraySchema(maxItems = 3) public List> withHelperClass; @ArraySchema(maxItems = 2) @JsonIgnoreProperties({"empty", "first", "last"}) public static interface Foo extends List { } @Size(max = 2) public List sized; @Retention(RetentionPolicy.RUNTIME) @Inherited public static @interface MySizeAnnotation { int maxItems() default Integer.MIN_VALUE; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/InnerType.java ================================================ package io.swagger.v3.core.resolving.resources; public class InnerType { public int foo; public String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/InnerTypeRequired.java ================================================ package io.swagger.v3.core.resolving.resources; import io.swagger.v3.oas.annotations.media.Schema; public class InnerTypeRequired { public int foo; @Schema(required = true) public String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/Issue4290.java ================================================ package io.swagger.v3.core.resolving.resources; import io.swagger.v3.oas.annotations.media.Schema; public class Issue4290 { @Schema(description = "A string, a number or a boolean", anyOf = { String.class, Number.class, Boolean.class }) public Object value; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/JacksonUnwrappedRequiredProperty.java ================================================ package io.swagger.v3.core.resolving.resources; import com.fasterxml.jackson.annotation.JsonUnwrapped; public class JacksonUnwrappedRequiredProperty { @JsonUnwrapped private final InnerTypeRequired innerType; public JacksonUnwrappedRequiredProperty(InnerTypeRequired innerType) { this.innerType = innerType; } public InnerTypeRequired getInnerType() { return innerType; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/JsonViewObject.java ================================================ package io.swagger.v3.core.resolving.resources; import com.fasterxml.jackson.annotation.JsonView; public class JsonViewObject { public static class View { public interface Public { } public interface Protected { } public interface Private { } } public static class Person { @JsonView({View.Public.class, View.Protected.class, View.Private.class}) public String id; @JsonView({View.Protected.class, View.Private.class}) public String firstName; @JsonView({View.Protected.class, View.Private.class}) public String lastName; @JsonView(View.Private.class) public String address; public String email; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/MyThing.java ================================================ package io.swagger.v3.core.resolving.resources; import io.swagger.v3.oas.annotations.media.Schema; import java.util.HashSet; import java.util.Set; @Schema(description = "Thing") public class MyThing { private final Set otherThings; public MyThing() { otherThings = new HashSet<>(); } @Schema(description = "Other related things") public Set getOtherThings() { return otherThings; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestArrayType.java ================================================ package io.swagger.v3.core.resolving.resources; import io.swagger.v3.oas.annotations.media.ArraySchema; import java.util.ArrayList; import java.util.List; public class TestArrayType { private Integer id; @ArraySchema(maxItems = 10) private List names; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public List getNames() { return names; } public void setNames(List names) { this.names = names; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject2616.java ================================================ package io.swagger.v3.core.resolving.resources; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; @Schema(name = "testObject") public class TestObject2616 { private List objects; @ArraySchema(schema = @Schema( name = "objects", oneOf = { AObject.class, BObject.class } )) public List getObjects() {return objects;} public void setObjects(List objects) {this.objects = objects;} public static class TestObject2616_Schema { private AbstractObject object; @Schema( name = "object", oneOf = { AObject.class, BObject.class } ) public AbstractObject getObjects() {return object;} public void setObject(AbstractObject object) {this.object = object;} } } abstract class AbstractObject {} @Schema(name = "AObject") class AObject extends AbstractObject{ private String name; public String getName() {return name;} public void setName(String name) {this.name = name;} } @Schema(name = "BObject") class BObject extends AbstractObject{ private Integer number; public Integer getNumber() {return number;} public void setNumber(Integer number) {this.number = number;} } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject2915.java ================================================ package io.swagger.v3.core.resolving.resources; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotNull; import java.io.Serializable; @Schema(name = "TestObject2616", description = "Nutritional value specification") public class TestObject2915 implements Serializable { private final static long serialVersionUID = 1L; private String name; private QuantitativeValueDTO perServing; private QuantitativeValueDTO per100Gram; public String getName() { return name; } public void setName(String name) { this.name = name; } public QuantitativeValueDTO getPerServing() { return perServing; } public void setPerServing(QuantitativeValueDTO perServing) { this.perServing = perServing; } public QuantitativeValueDTO getPer100Gram() { return per100Gram; } public void setPer100Gram(QuantitativeValueDTO per100Gram) { this.per100Gram = per100Gram; } @Schema(name = "QuantitativeValue", description = "A combination of a value and associated unit") public class QuantitativeValueDTO implements Serializable { private final static long serialVersionUID = 1L; @NotNull private double value; private String unitText; private String unitCode; public double getValue() { return value; } public void setValue(double value) { this.value = value; } public String getUnitText() { return unitText; } public void setUnitText(String unitText) { this.unitText = unitText; } public String getUnitCode() { return unitCode; } public void setUnitCode(String unitCode) { this.unitCode = unitCode; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject2972.java ================================================ package io.swagger.v3.core.resolving.resources; import java.util.Map; public class TestObject2972 { public Map myField1; public Map myField2; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject2992.java ================================================ package io.swagger.v3.core.resolving.resources; import java.time.LocalDateTime; import java.time.LocalTime; public class TestObject2992 { private String name; private LocalTime a; private LocalTime b; private LocalTime c; private LocalDateTime d; private LocalDateTime e; private LocalDateTime f; public LocalTime getA() { return a; } public void setA(LocalTime a) { this.a = a; } public LocalTime getB() { return b; } public void setB(LocalTime b) { this.b = b; } public LocalTime getC() { return c; } public void setC(LocalTime c) { this.c = c; } public LocalDateTime getD() { return d; } public void setD(LocalDateTime d) { this.d = d; } public LocalDateTime getE() { return e; } public void setE(LocalDateTime e) { this.e = e; } public LocalDateTime getF() { return f; } public void setF(LocalDateTime f) { this.f = f; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject3697.java ================================================ package io.swagger.v3.core.resolving.resources; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class TestObject3697 { @JsonProperty("id") private final Long id; @io.swagger.v3.oas.annotations.media.Schema(hidden = true) @JsonProperty("hidden") private final String hidden; @JsonCreator public TestObject3697(@JsonProperty("id") Long id, @io.swagger.v3.oas.annotations.media.Schema(hidden = true) @JsonProperty("hidden") String hidden) { this.id = id; this.hidden = hidden; } public Long getId() { return id; } public String getHidden() { return hidden; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject3699.java ================================================ package io.swagger.v3.core.resolving.resources; import java.util.List; @com.fasterxml.jackson.annotation.JsonTypeInfo( use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.WRAPPER_OBJECT) @com.fasterxml.jackson.annotation.JsonTypeName("CustomName") public class TestObject3699 { public String bar; public List foo; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObject4715.java ================================================ package io.swagger.v3.core.resolving.resources; public class TestObject4715 { private String foo; private String bar; private Integer id; public String getFoo() { return foo; } public void setFoo(String foo) { this.foo = foo; } public String getBar() { return bar; } public void setBar(String bar) { this.bar = bar; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObjectTicket2620.java ================================================ package io.swagger.v3.core.resolving.resources; import io.swagger.v3.oas.annotations.media.Schema; @Schema(name = "TestObjectTicket2620", description = "TestObject description", oneOf = { TestObjectTicket2620.ChildTestObject.class, TestObjectTicket2620.Child2TestObject.class }) public class TestObjectTicket2620 { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } class ChildTestObject extends TestObjectTicket2620{ private String childName; public String getChildName() { return childName; } public void setChildName(String childName) { this.childName = childName; } } class Child2TestObject extends TestObjectTicket2620{ private String childName; public String getChildName() { return childName; } public void setChildName(String childName) { this.childName = childName; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObjectTicket2620Subtypes.java ================================================ package io.swagger.v3.core.resolving.resources; import com.fasterxml.jackson.annotation.JsonSubTypes; import io.swagger.v3.oas.annotations.media.Schema; @Schema(name = "TestObjectTicket2620Subtypes", description = "TestObject description", oneOf = { TestObjectTicket2620Subtypes.ChildTestObject.class, TestObjectTicket2620Subtypes.Child2TestObject.class }) @JsonSubTypes({ @JsonSubTypes.Type(value = TestObjectTicket2620Subtypes.ChildTestObject.class), @JsonSubTypes.Type(value = TestObjectTicket2620Subtypes.Child2TestObject.class)}) public class TestObjectTicket2620Subtypes { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } class ChildTestObject extends TestObjectTicket2620Subtypes{ private String childName; public String getChildName() { return childName; } public void setChildName(String childName) { this.childName = childName; } } class Child2TestObject extends TestObjectTicket2620Subtypes{ private String childName; public String getChildName() { return childName; } public void setChildName(String childName) { this.childName = childName; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObjectTicket2900.java ================================================ package io.swagger.v3.core.resolving.resources; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; @Schema(name = "SomeDTO") public class TestObjectTicket2900 { @Schema(implementation = MyJsonPrimitive.class) public GsonJsonPrimitive value; @Schema( description = "Description of value", oneOf = { String.class, Number.class } ) public GsonJsonPrimitive valueWithMixIn; public class GsonJsonPrimitive { private String foo; public String getFoo(){return foo;} } @Schema( description = "Description of value", oneOf = { String.class, Number.class } ) public class MyJsonPrimitive { } public abstract class GsonJsonPrimitiveMixIn { @JsonIgnore public abstract String getFoo(); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/TestObjectTicket4247.java ================================================ package io.swagger.v3.core.resolving.resources; import io.swagger.v3.oas.annotations.media.Schema; public class TestObjectTicket4247 { @Schema( oneOf = { String.class, Number.class } ) public Object value; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/Ticket2862Model.java ================================================ package io.swagger.v3.core.resolving.resources; @com.fasterxml.jackson.annotation.JsonTypeInfo(use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.WRAPPER_OBJECT) @com.fasterxml.jackson.annotation.JsonSubTypes({ @com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = Ticket2862ModelImpl.class)}) public interface Ticket2862Model {} ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/Ticket2862ModelImpl.java ================================================ package io.swagger.v3.core.resolving.resources; public enum Ticket2862ModelImpl implements Ticket2862Model { VALUE1, VALUE2 } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/Ticket2884Model.java ================================================ package io.swagger.v3.core.resolving.resources; @com.fasterxml.jackson.annotation.JsonTypeInfo( use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.WRAPPER_OBJECT) public interface Ticket2884Model {} ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/Ticket2884ModelClass.java ================================================ package io.swagger.v3.core.resolving.resources; import java.util.List; @com.fasterxml.jackson.annotation.JsonTypeInfo( use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.WRAPPER_OBJECT) public class Ticket2884ModelClass { public String bar; public List foo; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/resources/User2169.java ================================================ package io.swagger.v3.core.resolving.resources; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; public class User2169 { private String name; private int age; private String privat; public String publi; private String getter; public String getGetter() { return getter; } private String setter; public void setSetter(String setter) { this.setter = setter; } private String getterSetter; public String getGetterSetter() { return getterSetter; } public void setGetterSetter(String getterSetter) { this.getterSetter = getterSetter; } @JsonProperty private String jsonProp; @JsonProperty(access = JsonProperty.Access.READ_ONLY) private String jsonPropReadOnly; @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String jsonPropWriteOnly; @JsonProperty(access = JsonProperty.Access.READ_WRITE) private String jsonPropReadWrite; private String getter_jsonProp; @JsonProperty public String getGetter_jsonProp() { return getter_jsonProp; } private String getter_jsonPropReadOnly; @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getGetter_jsonPropReadOnly() { return getter_jsonPropReadOnly; } // Doesn't expect writeOnly as it's semantically wrong? private String getter_jsonPropWriteOnly; @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public String getGetter_jsonPropWriteOnly() { return getter_jsonPropWriteOnly; } private String getter_jsonPropReadWrite; @JsonProperty(access = JsonProperty.Access.READ_WRITE) public String getGetter_jsonPropReadWrite() { return getter_jsonPropReadWrite; } private String setter_jsonProp; private String setter_jsonPropReadOnly; private String setter_jsonPropWriteOnly; private String setter_jsonPropReadWrite; @JsonProperty public void setSetter_jsonProp(String setter_jsonProp) { this.setter_jsonProp = setter_jsonProp; } // Doesn't expect readOnly as it's semantically wrong? @JsonProperty(access = JsonProperty.Access.READ_ONLY) public void setSetter_jsonPropReadOnly(String setter_jsonPropReadOnly) { this.setter_jsonPropReadOnly = setter_jsonPropReadOnly; } @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public void setSetter_jsonPropWriteOnly(String setter_jsonPropWriteOnly) { this.setter_jsonPropWriteOnly = setter_jsonPropWriteOnly; } @JsonProperty(access = JsonProperty.Access.READ_WRITE) public void setSetter_jsonPropReadWrite(String setter_jsonPropReadWrite) { this.setter_jsonPropReadWrite = setter_jsonPropReadWrite; } private String gettersetter_jsonPropGet; private String gettersetter_jsonPropReadOnlyGet; private String gettersetter_jsonPropWriteOnlyGet; private String gettersetter_jsonPropReadWriteGet; private String gettersetter_jsonPropSet; private String gettersetter_jsonPropReadOnlySet; private String gettersetter_jsonPropWriteOnlySet; private String gettersetter_jsonPropReadWriteSet; @JsonProperty public String getGettersetter_jsonPropGet() { return gettersetter_jsonPropGet; } public void setGettersetter_jsonPropGet(String gettersetter_jsonPropGet) { this.gettersetter_jsonPropGet = gettersetter_jsonPropGet; } @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getGettersetter_jsonPropReadOnlyGet() { return gettersetter_jsonPropReadOnlyGet; } public void setGettersetter_jsonPropReadOnlyGet(String gettersetter_jsonPropReadOnlyGet) { this.gettersetter_jsonPropReadOnlyGet = gettersetter_jsonPropReadOnlyGet; } @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public String getGettersetter_jsonPropWriteOnlyGet() { return gettersetter_jsonPropWriteOnlyGet; } public void setGettersetter_jsonPropWriteOnlyGet(String gettersetter_jsonPropWriteOnlyGet) { this.gettersetter_jsonPropWriteOnlyGet = gettersetter_jsonPropWriteOnlyGet; } @JsonProperty(access = JsonProperty.Access.READ_WRITE) public String getGettersetter_jsonPropReadWriteGet() { return gettersetter_jsonPropReadWriteGet; } public void setGettersetter_jsonPropReadWriteGet(String gettersetter_jsonPropReadWriteGet) { this.gettersetter_jsonPropReadWriteGet = gettersetter_jsonPropReadWriteGet; } public String getGettersetter_jsonPropSet() { return gettersetter_jsonPropSet; } @JsonProperty public void setGettersetter_jsonPropSet(String gettersetter_jsonPropSet) { this.gettersetter_jsonPropSet = gettersetter_jsonPropSet; } public String getGettersetter_jsonPropReadOnlySet() { return gettersetter_jsonPropReadOnlySet; } @JsonProperty(access = JsonProperty.Access.READ_ONLY) public void setGettersetter_jsonPropReadOnlySet(String gettersetter_jsonPropReadOnlySet) { this.gettersetter_jsonPropReadOnlySet = gettersetter_jsonPropReadOnlySet; } public String getGettersetter_jsonPropWriteOnlySet() { return gettersetter_jsonPropWriteOnlySet; } @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public void setGettersetter_jsonPropWriteOnlySet(String gettersetter_jsonPropWriteOnlySet) { this.gettersetter_jsonPropWriteOnlySet = gettersetter_jsonPropWriteOnlySet; } public String getGettersetter_jsonPropReadWriteSet() { return gettersetter_jsonPropReadWriteSet; } @JsonProperty(access = JsonProperty.Access.READ_WRITE) public void setGettersetter_jsonPropReadWriteSet(String gettersetter_jsonPropReadWriteSet) { this.gettersetter_jsonPropReadWriteSet = gettersetter_jsonPropReadWriteSet; } private String getterIgnore_setter; private String getterIgnore_jsonPropSet; private String getterIgnore_jsonPropReadOnlySet; private String getterIgnore_jsonPropWriteOnlySet; private String getterIgnore_jsonPropReadWriteSet; @JsonIgnore public String getGetterIgnore_setter() { return getterIgnore_setter; } public void setGetterIgnore_setter(String getterIgnore_setter) { this.getterIgnore_setter = getterIgnore_setter; } @JsonIgnore public String getGetterIgnore_jsonPropSet() { return getterIgnore_jsonPropSet; } @JsonProperty public void setGetterIgnore_jsonPropSet(String getterIgnore_jsonPropSet) { this.getterIgnore_jsonPropSet = getterIgnore_jsonPropSet; } @JsonIgnore public String getGetterIgnore_jsonPropReadOnlySet() { return getterIgnore_jsonPropReadOnlySet; } @JsonProperty(access = JsonProperty.Access.READ_ONLY) public void setGetterIgnore_jsonPropReadOnlySet(String getterIgnore_jsonPropReadOnlySet) { this.getterIgnore_jsonPropReadOnlySet = getterIgnore_jsonPropReadOnlySet; } @JsonIgnore public String getGetterIgnore_jsonPropWriteOnlySet() { return getterIgnore_jsonPropWriteOnlySet; } @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public void setGetterIgnore_jsonPropWriteOnlySet(String getterIgnore_jsonPropWriteOnlySet) { this.getterIgnore_jsonPropWriteOnlySet = getterIgnore_jsonPropWriteOnlySet; } @JsonIgnore public String getGetterIgnore_jsonPropReadWriteSet() { return getterIgnore_jsonPropReadWriteSet; } @JsonProperty(access = JsonProperty.Access.READ_WRITE) public void setGetterIgnore_jsonPropReadWriteSet(String getterIgnore_jsonPropReadWriteSet) { this.getterIgnore_jsonPropReadWriteSet = getterIgnore_jsonPropReadWriteSet; } private String setterIgnore_getter; private String setterIgnore_jsonPropGet; private String setterIgnore_jsonPropReadOnlyGet; private String setterIgnore_jsonPropWriteOnlyGet; private String setterIgnore_jsonPropReadWriteGet; public String getSetterIgnore_getter() { return setterIgnore_getter; } @JsonIgnore public void setSetterIgnore_getter(String setterIgnore_getter) { this.setterIgnore_getter = setterIgnore_getter; } @JsonProperty public String getSetterIgnore_jsonPropGet() { return setterIgnore_jsonPropGet; } @JsonIgnore public void setSetterIgnore_jsonPropGet(String setterIgnore_jsonPropGet) { this.setterIgnore_jsonPropGet = setterIgnore_jsonPropGet; } @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getSetterIgnore_jsonPropReadOnlyGet() { return setterIgnore_jsonPropReadOnlyGet; } @JsonIgnore public void setSetterIgnore_jsonPropReadOnlyGet(String setterIgnore_jsonPropReadOnlyGet) { this.setterIgnore_jsonPropReadOnlyGet = setterIgnore_jsonPropReadOnlyGet; } @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public String getSetterIgnore_jsonPropWriteOnlyGet() { return setterIgnore_jsonPropWriteOnlyGet; } @JsonIgnore public void setSetterIgnore_jsonPropWriteOnlyGet(String setterIgnore_jsonPropWriteOnlyGet) { this.setterIgnore_jsonPropWriteOnlyGet = setterIgnore_jsonPropWriteOnlyGet; } @JsonProperty(access = JsonProperty.Access.READ_WRITE) public String getSetterIgnore_jsonPropReadWriteGet() { return setterIgnore_jsonPropReadWriteGet; } @JsonIgnore public void setSetterIgnore_jsonPropReadWriteGet(String setterIgnore_jsonPropReadWriteGet) { this.setterIgnore_jsonPropReadWriteGet = setterIgnore_jsonPropReadWriteGet; } @JsonProperty(value = "GetterJsonPropertyOnField", required = true) private String getterJsonPropertyOnField; @JsonProperty(value = "GetterJsonPropertyOnFieldReadWrite", required = true, access = JsonProperty.Access.READ_WRITE) private String getterJsonPropertyOnFieldReadWrite; @Schema(accessMode = Schema.AccessMode.READ_WRITE) @JsonProperty(value = "GetterJsonPropertyOnFieldReadWriteSchemaReadOnlyFalse", required = true, access = JsonProperty.Access.READ_WRITE) private String getterJsonPropertyOnFieldReadWriteSchemaReadOnlyFalse; @JsonProperty(value = "GetterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse", required = true, access = JsonProperty.Access.READ_WRITE) @Schema(accessMode = Schema.AccessMode.READ_WRITE) private String getterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse; @JsonProperty(value = "GetterJsonPropertyOnFieldReadOnly", required = true, access = JsonProperty.Access.READ_ONLY) private String getterJsonPropertyOnFieldReadOnly; @Schema(accessMode = Schema.AccessMode.READ_ONLY) @JsonProperty(value = "GetterJsonPropertyOnFieldSchemaReadOnlyTrue", required = true) private String getterJsonPropertyOnFieldSchemaReadOnlyTrue; @Schema(accessMode = Schema.AccessMode.READ_ONLY) private String getterSchemaReadOnlyTrue; @JsonCreator public User2169(@JsonProperty(value = "Name", required = true) String name, @JsonProperty(value = "Age", required = true) int age, @JsonProperty(value = "GetterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse", required = true, access = JsonProperty.Access.READ_WRITE) String getterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse) { this.name = name; this.age = age; this.getterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse = getterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse; } @JsonProperty(value = "Name", required = true) public String getName() { return name; } @JsonProperty(value = "Age", required = true) public int getAge() { return age; } public String getGetterJsonPropertyOnField() { return getterJsonPropertyOnField; } public String getGetterJsonPropertyOnFieldReadWrite() { return getterJsonPropertyOnFieldReadWrite; } public String getGetterJsonPropertyOnFieldReadWriteSchemaReadOnlyFalse() { return getterJsonPropertyOnFieldReadWriteSchemaReadOnlyFalse; } public String getGetterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse() { return getterJsonPropertyOnFieldReadWriteCreatorSchemaReadOnlyFalse; } public String getGetterJsonPropertyOnFieldReadOnly() { return getterJsonPropertyOnFieldReadOnly; } public String getGetterJsonPropertyOnFieldSchemaReadOnlyTrue() { return getterJsonPropertyOnFieldSchemaReadOnlyTrue; } public String getGetterSchemaReadOnlyTrue() { return getterSchemaReadOnlyTrue; } Boolean isApprovePairing; @JsonIgnore public Boolean isApprovePairing() { return isApprovePairing; } @JsonProperty(value = "approvePairing", access = JsonProperty.Access.WRITE_ONLY) public void setApprovePairing(boolean isApprovePairing) { this.isApprovePairing = isApprovePairing; } // not supported as not supported in json-ref; see discussion in https://github.com/OAI/OpenAPI-Specification/issues/556 @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private Data data; } class Data { public String foo; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java ================================================ package io.swagger.v3.core.resolving.v31; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.SwaggerTestBase; import io.swagger.v3.core.resolving.resources.TestArrayType; import io.swagger.v3.core.resolving.resources.TestObject4715; import io.swagger.v3.core.resolving.v31.model.AnnotatedArray; import io.swagger.v3.core.resolving.v31.model.AnnotatedArrayProperty; import io.swagger.v3.core.resolving.v31.model.AnnotatedArrayPropertyWriteOnly; import io.swagger.v3.core.resolving.v31.model.AnnotatedArrayPropertyReadWrite; import io.swagger.v3.core.resolving.v31.model.ModelWithDependentSchema; import io.swagger.v3.core.resolving.v31.model.ModelWithOAS31Stuff; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import java.util.List; import java.util.Map; public class ModelResolverOAS31Test extends SwaggerTestBase { @Test public void testAnnotatedArray() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(AnnotatedArray.class)); SerializationMatchers.assertEqualsToYaml31(model, "type: array\n" + "contains:\n" + " type: string\n" + "description: arraydescription\n" + "items:\n" + " type: string\n" + " description: itemdescription\n"+ "maxContains: 10\n" + "minContains: 1\n" + "prefixItems:\n" + "- type: string\n" + "unevaluatedItems:\n" + " type: number\n"); } @Test public void testAnnotatedArrayProperty() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(AnnotatedArrayProperty.class)); SerializationMatchers.assertEqualsToYaml31(model, "type: object\n" + "properties:\n" + " randomList:\n" + " type: array\n" + " contains:\n" + " type: string\n" + " deprecated: true\n" + " description: arraydescription\n" + " examples:\n" + " - John\n" + " items:\n" + " type: string\n" + " description: itemdescription\n" + " title: itemtitle\n" + " maxContains: 10\n" + " minContains: 1\n" + " prefixItems:\n" + " - type: string\n" + " description: prefixdescription\n" + " readOnly: true\n" + " title: arraytitle\n" + " unevaluatedItems:\n" + " type: number"); } @Test public void testAnnotatedArrayPropertyWriteOnly() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(AnnotatedArrayPropertyWriteOnly.class)); SerializationMatchers.assertEqualsToYaml31(model, "type: object\n" + "properties:\n" + " randomList:\n" + " type: array\n" + " description: arraydescription\n" + " examples:\n" + " - Jane\n" + " items:\n" + " type: string\n" + " description: itemdescription\n" + " title: itemtitle\n" + " maxContains: 5\n" + " minContains: 1\n" + " title: arraytitle\n" + " writeOnly: true"); } @Test public void testAnnotatedArrayPropertyReadWrite() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(AnnotatedArrayPropertyReadWrite.class)); SerializationMatchers.assertEqualsToYaml31(model, "type: object\n" + "properties:\n" + " randomList:\n" + " type: array\n" + " description: arraydescription\n" + " examples:\n" + " - Bob\n" + " items:\n" + " type: string\n" + " description: itemdescription\n" + " title: itemtitle\n" + " maxContains: 8\n" + " minContains: 2\n" + " title: arraytitle"); } @Test public void testOAS31Fields() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context.resolve(new AnnotatedType(ModelWithOAS31Stuff.class)); SerializationMatchers.assertEqualsToYaml31(context.getDefinedModels(), "Address:\n" + " type: object\n" + " if:\n" + " $ref: \"#/components/schemas/AnnotatedCountry\"\n" + " then:\n" + " $ref: \"#/components/schemas/PostalCodeNumberPattern\"\n" + " else:\n" + " $ref: \"#/components/schemas/PostalCodePattern\"\n" + " dependentRequired:\n" + " street:\n" + " - country\n" + " properties:\n" + " street:\n" + " type: string\n" + " country:\n" + " type: string\n" + " enum:\n" + " - UNITED_STATES_OF_AMERICA\n" + " - CANADA\n" + " propertyNames:\n" + " pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\"\n" + "AnnotatedCountry:\n" + " type: object\n" + " properties:\n" + " country:\n" + " type: string\n" + " const: United States\n" + "Client:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " creditCard:\n" + " type: integer\n" + " format: int32\n" + "CreditCard:\n" + " type: object\n" + " properties:\n" + " billingAddress:\n" + " type: string\n" + " acceptingCountries:\n" + " type: array\n" + " items:\n" + " type: string\n" + " description: accepting country\n" + " enum:\n" + " - UNITED_STATES_OF_AMERICA\n" + " - CANADA\n" + " uniqueItems: true\n" + " availableCurrencies:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Currency\"\n" + " description: available currencies\n" + " uniqueItems: true\n" + "Currency:\n" + " type: object\n" + " properties:\n" + " currencyCode:\n" + " type: string\n" + "ModelWithOAS31Stuff:\n" + " type: object\n" + " $comment: Random comment at schema level\n" + " $id: http://yourdomain.com/schemas/myschema.json\n" + " description: this is model for testing OAS 3.1 resolving\n" + " properties:\n" + " randomList:\n" + " type: array\n" + " contains:\n" + " type: string\n" + " description: arraydescription\n" + " items:\n" + " type: string\n" + " description: itemdescription\n" + " title: itemtitle\n" + " maxContains: 10\n" + " minContains: 1\n" + " prefixItems:\n" + " - type: string\n" + " title: arraytitle\n" + " unevaluatedItems:\n" + " type: number\n" + " status:\n" + " type:\n" + " - string\n" + " - number\n" + " intValue:\n" + " type: integer\n" + " format: int32\n" + " $anchor: intValue\n" + " $comment: comment at schema property level\n" + " exclusiveMaximum: 100\n" + " exclusiveMinimum: 1\n" + " text:\n" + " type: string\n" + " contentEncoding: plan/text\n" + " contentMediaType: base64\n" + " encodedString:\n" + " type: string\n" + " contentMediaType: application/jwt\n" + " contentSchema:\n" + " $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " address:\n" + " $ref: \"#/components/schemas/Address\"\n" + " client:\n" + " $ref: \"#/components/schemas/Client\"\n" + " dependentSchemas:\n" + " creditCard:\n" + " $ref: \"#/components/schemas/CreditCard\"\n" + " patternProperties:\n" + " creditCard:\n" + " $ref: \"#/components/schemas/CreditCard\"\n" + " properties:\n" + " extraObject:\n" + " type: object\n" + "MultipleBaseBean:\n" + " type: object\n" + " description: MultipleBaseBean\n" + " properties:\n" + " beanType:\n" + " type: string\n" + " a:\n" + " type: integer\n" + " format: int32\n" + " b:\n" + " type: string\n" + "MultipleSub1Bean:\n" + " allOf:\n" + " - $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " - type: object\n" + " properties:\n" + " c:\n" + " type: integer\n" + " format: int32\n" + " description: MultipleSub1Bean\n" + "MultipleSub2Bean:\n" + " allOf:\n" + " - $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " - type: object\n" + " properties:\n" + " d:\n" + " type: integer\n" + " format: int32\n" + " description: MultipleSub2Bean\n" + "PostalCodeNumberPattern:\n" + " type: object\n" + " properties:\n" + " postalCode:\n" + " type: string\n" + " pattern: \"[0-9]{5}(-[0-9]{4})?\"\n" + "PostalCodePattern:\n" + " type: object\n" + " properties:\n" + " postalCode:\n" + " type: string\n" + " pattern: \"[A-Z][0-9][A-Z] [0-9][A-Z][0-9]\"\n" + "PropertyNamesPattern:\n" + " pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\"\n"); } @Test public void testDependentSchemasAnnotation() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(ModelWithDependentSchema.class)); SerializationMatchers.assertEqualsToYaml31(context.getDefinedModels(), "BooleanFakeClass:\n" + " type: object\n" + " properties:\n" + " type:\n" + " type: boolean\n" + "ModelWithDependentSchema:\n" + " type: object\n" + " dependentSchemas:\n" + " value:\n" + " properties:\n" + " enable:\n" + " $ref: \"#/components/schemas/BooleanFakeClass\"\n" + " properties:\n" + " name:\n" + " type: string\n" + " value:\n" + " type: integer\n" + " format: int32\n"); } @Test(description = "Top level type:object should appear in OAS31") public void testObjectTypeSchemaOAS31(){ final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(TestObject4715.class)); SerializationMatchers.assertEqualsToYaml31(model, "type: object\n" + "properties:\n" + " foo:\n" + " type: string\n" + " bar:\n" + " type: string\n" + " id:\n" + " type: integer\n" + " format: int32"); } @Test public void testFieldArraySchemaAnnotation() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(TestArrayType.class)); SerializationMatchers.assertEqualsToYaml31(model, " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int32\n" + " names:\n" + " type: array\n" + " items:\n" + " type: string\n" + " maxItems: 10"); } @Test(description = "@Pattern correctly handled in type parameters of properties using collections when using oas 3.1.0") public void testModelUsingCollectionTypePropertyHandlesPatternAnnotationForOas31() { String expectedYaml = "ClassWithUsingPatternOnCollection:\n" + " type: object\n" + " properties:\n" + " myField:\n" + " type: array\n" + " items:\n" + " pattern: myPattern\n" + " type: string"; Map stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingPatternOnCollection.class); SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); } private static class ClassWithUsingPatternOnCollection { private List<@Pattern(regexp = "myPattern") String> myField; public List getMyField() { return myField; } public void setMyField(List myField) { this.myField = myField; } } @Test(description = "@Size correctly handled in properties using collections when using oas 3.1.0") public void testModelUsingCollectionTypePropertyHandleSizeAnnotationForOas31() { String expectedYaml = "ClassWithUsingSizeOnCollection:\n" + " type: object\n" + " properties:\n" + " myField:\n" + " maxItems: 100\n" + " minItems: 1\n" + " type: array\n" + " items:\n" + " type: string"; Map stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingSizeOnCollection.class); SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); } private static class ClassWithUsingSizeOnCollection { @Size(min = 1, max = 100) private List myField; public List getMyField() { return myField; } public void setMyField(List myField) { this.myField = myField; } } @Test(description = "@Size correctly handled for field type String using OAS 3.1.0") public void testSizeAnnotationOnFieldForOAS31() { String expectedYaml = "ClassWithUsingSizeOnField:\n" + " type: object\n" + " properties:\n" + " myField:\n" + " type: string\n" + " maxLength: 100\n" + " minLength: 1"; Map stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingSizeOnField.class); SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); } private static class ClassWithUsingSizeOnField { @Size(min = 1, max = 100) private String myField; public String getMyField() { return myField; } public void setMyField(String myField) { this.myField = myField; } } @Test(description = "@DecimalMax/Min annotations correctly handled for field type Number using OAS 3.1.0") public void testDecimalAnnotationsOnField() { String expectedYaml = "ClassWithUsingDecimalAnnotationsOnField:\n" + " type: object\n" + " properties:\n" + " myField:\n" + " type: number\n" + " maximum: 100\n" + " minimum: 1"; Map stringSchemaMap = ModelConverters.getInstance(true).readAll(ClassWithUsingDecimalAnnotationsOnField.class); SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); } private static class ClassWithUsingDecimalAnnotationsOnField { @DecimalMin("1") @DecimalMax("100") private Number myField; public Number getMyField() { return myField; } public void setMyField(Number myField) { this.myField = myField; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/PatternAndSchemaPropertiesTest.java ================================================ package io.swagger.v3.core.resolving.v31; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.SwaggerTestBase; import io.swagger.v3.core.resolving.v31.model.AnnotatedPet; import io.swagger.v3.core.resolving.v31.model.AnnotatedPetSinglePatternProperty; import io.swagger.v3.core.util.OpenAPISchema2JsonSchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; public class PatternAndSchemaPropertiesTest extends SwaggerTestBase { @Test public void testPatternAndSchemaProperties() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(AnnotatedPet.class)); assertEquals(((Schema)model.getPatternProperties().get("what.*ever")).getFormat(), "int32"); assertEquals(((Schema)model.getPatternProperties().get("it.*takes")).get$ref(), "#/components/schemas/Category"); assertEquals(((Schema)model.getProperties().get("anotherCategory")).get$ref(), "#/components/schemas/Category"); assertEquals(((Schema)model.getProperties().get("anotherInteger")).getFormat(), "int32"); SerializationMatchers.assertEqualsToYaml(context.getDefinedModels(), "AnnotatedPet:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " category:\n" + " $ref: \"#/components/schemas/Category\"\n" + " name:\n" + " type: string\n" + " photoUrls:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " type: string\n" + " xml:\n" + " name: photoUrl\n" + " tags:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " $ref: \"#/components/schemas/Tag\"\n" + " status:\n" + " type: string\n" + " description: pet status in the store\n" + " enum:\n" + " - available\n" + " - pending\n" + " - sold\n" + " anotherCategory:\n" + " $ref: \"#/components/schemas/Category\"\n" + " anotherInteger:\n" + " maximum: 10\n" + " type: integer\n" + " description: prop schema 1\n" + " format: int32\n" + " description: Annotated Pet\n" + " nullable: true\n" + "Category:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " description: prop schema 2\n" + " xml:\n" + " name: Category\n" + "Tag:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Tag"); context.getDefinedModels().values().forEach(s -> new OpenAPISchema2JsonSchema().process(s)); SerializationMatchers.assertEqualsToYaml31(context.getDefinedModels(), "AnnotatedPet:\n" + " type:\n" + " - object\n" + " - \"null\"\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " category:\n" + " $ref: \"#/components/schemas/Category\"\n" + " name:\n" + " type: string\n" + " photoUrls:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " type: string\n" + " xml:\n" + " name: photoUrl\n" + " tags:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " $ref: \"#/components/schemas/Tag\"\n" + " status:\n" + " type: string\n" + " description: pet status in the store\n" + " enum:\n" + " - available\n" + " - pending\n" + " - sold\n" + " anotherCategory:\n" + " $ref: \"#/components/schemas/Category\"\n" + " anotherInteger:\n" + " maximum: 10\n" + " type: integer\n" + " description: prop schema 1\n" + " format: int32\n" + " patternProperties:\n" + " what.*ever:\n" + " maximum: 10\n" + " type: integer\n" + " description: prop schema 1\n" + " format: int32\n" + " it.*takes:\n" + " $ref: \"#/components/schemas/Category\"\n" + " description: Annotated Pet\n" + "Category:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " description: prop schema 2\n" + " xml:\n" + " name: Category\n" + "Tag:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Tag\n"); } @Test public void testSinglePatternAndSchemaProperties() throws Exception { final ModelResolver modelResolver = new ModelResolver(mapper()); ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); Schema model = context .resolve(new AnnotatedType(AnnotatedPetSinglePatternProperty.class)); assertEquals(((Schema)model.getPatternProperties().get("what.*ever")).getFormat(), "int32"); assertEquals(((Schema)model.getProperties().get("anotherCategory")).get$ref(), "#/components/schemas/Category"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/StreamWithArraySchemaTest.java ================================================ package io.swagger.v3.core.resolving.v31; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.resolving.SwaggerTestBase; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import org.testng.annotations.Test; import java.util.stream.Stream; import static org.testng.Assert.*; /** * Test for issue #5013: @ArraySchema applied on a stream property results in object type in OAS 3.1 */ public class StreamWithArraySchemaTest extends SwaggerTestBase { @Test public void testStreamPropertyWithArraySchemaOAS31() { ModelResolver resolver = new ModelResolver(mapper()).openapi31(true); ModelConverterContextImpl context = new ModelConverterContextImpl(resolver); io.swagger.v3.oas.models.media.Schema model = resolver.resolve( new AnnotatedType().type(ModelWithStream.class), context, null ); assertNotNull(model); io.swagger.v3.oas.models.media.Schema greetingsProperty = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("greetings"); assertNotNull(greetingsProperty); assertNotNull(greetingsProperty.getTypes()); assertTrue(greetingsProperty.getTypes().contains("array"), "Expected types to contain 'array' but got: " + greetingsProperty.getTypes()); assertFalse(greetingsProperty.getTypes().contains("object")); assertNotNull(greetingsProperty.getItems()); assertEquals(greetingsProperty.getItems().get$ref(), "#/components/schemas/Greeting"); assertNull(greetingsProperty.getProperties()); } @Test public void testStreamPropertyWithoutArraySchemaOAS31() { ModelResolver resolver = new ModelResolver(mapper()).openapi31(true); ModelConverterContextImpl context = new ModelConverterContextImpl(resolver); io.swagger.v3.oas.models.media.Schema model = resolver.resolve( new AnnotatedType().type(ModelWithStreamNoAnnotation.class), context, null ); assertNotNull(model); io.swagger.v3.oas.models.media.Schema itemsProperty = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("items"); assertNotNull(itemsProperty); assertTrue(itemsProperty.getTypes().contains("object")); assertFalse(itemsProperty.getTypes() != null && itemsProperty.getTypes().contains("array")); } @Test public void testStreamPropertyWithoutArraySchemaOAS30() { ModelResolver resolver = new ModelResolver(mapper()).openapi31(false); ModelConverterContextImpl context = new ModelConverterContextImpl(resolver); io.swagger.v3.oas.models.media.Schema model = resolver.resolve( new AnnotatedType().type(ModelWithStreamNoAnnotation.class), context, null ); assertNotNull(model); io.swagger.v3.oas.models.media.Schema itemsProperty = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("items"); assertNotNull(itemsProperty); assertEquals(itemsProperty.getType(), "object"); assertNotEquals(itemsProperty.getType(), "array"); } @Test public void testStreamPropertyWithArraySchemaOAS30() { ModelResolver resolver = new ModelResolver(mapper()).openapi31(false); ModelConverterContextImpl context = new ModelConverterContextImpl(resolver); io.swagger.v3.oas.models.media.Schema model = resolver.resolve( new AnnotatedType().type(ModelWithStream.class), context, null ); assertNotNull(model); io.swagger.v3.oas.models.media.Schema greetingsProperty = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("greetings"); assertNotNull(greetingsProperty); assertEquals(greetingsProperty.getType(), "array"); assertNotNull(greetingsProperty.getItems()); assertEquals(greetingsProperty.getItems().get$ref(), "#/components/schemas/Greeting"); assertNull(greetingsProperty.getProperties()); } @Test public void testStreamPropertyWithDetailedAnnotations() { ModelResolver resolver = new ModelResolver(mapper()).openapi31(true); ModelConverterContextImpl context = new ModelConverterContextImpl(resolver); io.swagger.v3.oas.models.media.Schema model = resolver.resolve( new AnnotatedType().type(ModelWithDetailedStreamAnnotations.class), context, null ); assertNotNull(model); io.swagger.v3.oas.models.media.Schema greetingsProperty = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("greetings"); assertNotNull(greetingsProperty); assertNotNull(greetingsProperty.getTypes()); assertTrue(greetingsProperty.getTypes().contains("array")); assertNotNull(greetingsProperty.getItems()); assertEquals(greetingsProperty.getItems().get$ref(), "#/components/schemas/Greeting"); assertEquals(greetingsProperty.getMinItems(), Integer.valueOf(1)); assertEquals(greetingsProperty.getMaxItems(), Integer.valueOf(10)); assertTrue(greetingsProperty.getUniqueItems()); assertEquals(greetingsProperty.getDescription(), "A collection of greetings"); } @Test public void testListPropertyWithDetailedAnnotations() { ModelResolver resolver = new ModelResolver(mapper()).openapi31(true); ModelConverterContextImpl context = new ModelConverterContextImpl(resolver); io.swagger.v3.oas.models.media.Schema model = resolver.resolve( new AnnotatedType().type(ModelWithDetailedListAnnotations.class), context, null ); assertNotNull(model); io.swagger.v3.oas.models.media.Schema greetingsProperty = (io.swagger.v3.oas.models.media.Schema) model.getProperties().get("greetings"); assertNotNull(greetingsProperty); } public static class ModelWithStream { @ArraySchema(schema = @Schema(implementation = Greeting.class)) private Stream greetings; public Stream getGreetings() { return greetings; } public void setGreetings(Stream greetings) { this.greetings = greetings; } } public static class Greeting { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } public static class ModelWithStreamNoAnnotation { private Stream items; public Stream getItems() { return items; } public void setItems(Stream items) { this.items = items; } } public static class ModelWithDetailedStreamAnnotations { @ArraySchema( minItems = 1, maxItems = 10, uniqueItems = true, arraySchema = @Schema( description = "A collection of greetings", example = "[{\"message\": \"Hello\"}]" ), schema = @Schema(implementation = Greeting.class) ) private Stream greetings; public Stream getGreetings() { return greetings; } public void setGreetings(Stream greetings) { this.greetings = greetings; } } public static class ModelWithDetailedListAnnotations { @ArraySchema( minItems = 1, maxItems = 10, uniqueItems = true, arraySchema = @Schema( description = "A collection of greetings", example = "[{\"message\": \"Hello\"}]" ), schema = @Schema(implementation = Greeting.class) ) private java.util.List greetings; public java.util.List getGreetings() { return greetings; } public void setGreetings(java.util.List greetings) { this.greetings = greetings; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/Ticket3900Test.java ================================================ package io.swagger.v3.core.resolving.v31; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.resolving.SwaggerTestBase; import org.testng.annotations.Test; public class Ticket3900Test extends SwaggerTestBase { @Test public void testArraySchemaItemsValidation() { final ModelResolver modelResolver = new ModelResolver(mapper()).openapi31(true); final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); io.swagger.v3.oas.models.media.Schema model = context.resolve(new AnnotatedType(Route.class)); SerializationMatchers.assertEqualsToYaml31(model, "type: object\n" + "properties:\n" + " startPoint:\n" + " $ref: '#/components/schemas/GeoPoint'\n" + " description: Point where the route begins\n" + " intermediatePoint:\n" + " $ref: '#/components/schemas/GeoPoint'\n" + " description: Intermediate point of the route\n" + " endPoint:\n" + " $ref: '#/components/schemas/GeoPoint'\n" + " description: Point where the route ends"); } private static class GeoPoint { @io.swagger.v3.oas.annotations.media.Schema(description = "Longitude of geo point ( -180, 180 >") public double lon; @io.swagger.v3.oas.annotations.media.Schema(description = "Latitude of geo point < -90, 90 >") public double lat; } private static class Route { @io.swagger.v3.oas.annotations.media.Schema(description = "Point where the route begins") public GeoPoint startPoint; @io.swagger.v3.oas.annotations.media.Schema(description = "Intermediate point of the route") public GeoPoint intermediatePoint; @io.swagger.v3.oas.annotations.media.Schema(description = "Point where the route ends") public GeoPoint endPoint; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/Address.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.DependentRequired; import io.swagger.v3.oas.annotations.media.Schema; @Schema( _if = Address.AnnotatedCountry.class, then = PostalCodeNumberPattern.class, _else = PostalCodePattern.class, propertyNames = Address.PropertyNamesPattern.class, dependentRequiredMap = { @DependentRequired( name = "street", value = { "country" } ) } ) public class Address { private String street; private CountryEnum country; public enum CountryEnum { UNITED_STATES_OF_AMERICA("United States of America"), CANADA("Canada"); private String value; CountryEnum(String value) { this.value = value; } public String getValue() { return value; } @Override public String toString() { return String.valueOf(value); } public static CountryEnum fromValue(String value) { for (CountryEnum b : CountryEnum.values()) { if (b.value.equals(value)) { return b; } } return null; } } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public CountryEnum getCountry() { return country; } public void setCountry(CountryEnum country) { this.country = country; } class AnnotatedCountry { private Object country; @Schema( _const = "United States", type = "string" ) public Object getCountry() { return country; } public void setCountry(Object country) { this.country = country; } } @Schema( pattern = "^[A-Za-z_][A-Za-z0-9_]*$" ) class PropertyNamesPattern { } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/AnnotatedArray.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; @ArraySchema( maxContains = 10, minContains = 1, contains = @Schema( types = { "string" } ), unevaluatedItems = @Schema( types = { "number" } ), schema = @Schema( types = { "string" }, description = "itemdescription" ), arraySchema = @Schema(description = "arraydescription"), prefixItems = { @Schema( types = { "string" } ) } ) public class AnnotatedArray { } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/AnnotatedArrayProperty.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; public class AnnotatedArrayProperty { private List randomList; @ArraySchema( schema = @Schema( types = { "string" }, description = "itemdescription", title = "itemtitle" ), arraySchema = @Schema( description = "arraydescription", title = "arraytitle", deprecated = true, accessMode = Schema.AccessMode.READ_ONLY, examples = "John"), maxContains = 10, minContains = 1, contains = @Schema( types = "string" ), unevaluatedItems = @Schema( types = "number" ), prefixItems = { @Schema( description = "prefixdescription", types = "string" ) } ) public List getRandomList() { return randomList; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/AnnotatedArrayPropertyReadWrite.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; public class AnnotatedArrayPropertyReadWrite { private List randomList; @ArraySchema( schema = @Schema( types = { "string" }, description = "itemdescription", title = "itemtitle" ), arraySchema = @Schema( description = "arraydescription", title = "arraytitle", accessMode = Schema.AccessMode.READ_WRITE, examples = "Bob"), maxContains = 8, minContains = 2 ) public List getRandomList() { return randomList; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/AnnotatedArrayPropertyWriteOnly.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; public class AnnotatedArrayPropertyWriteOnly { private List randomList; @ArraySchema( schema = @Schema( types = { "string" }, description = "itemdescription", title = "itemtitle" ), arraySchema = @Schema( description = "arraydescription", title = "arraytitle", accessMode = Schema.AccessMode.WRITE_ONLY, examples = "Jane"), maxContains = 5, minContains = 1 ) public List getRandomList() { return randomList; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/AnnotatedPet.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.PatternProperty; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.SchemaProperty; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import java.util.ArrayList; import java.util.List; @Schema(description = "Annotated Pet", nullable = true) @PatternProperty( regex = "what.*ever", schema = @Schema( type = "integer", description = "prop schema 1", format = "int32", maximum = "10" ) ) @PatternProperty( regex = "it.*takes", schema = @Schema( implementation = Category.class, description = "prop schema 2" ) ) @SchemaProperty( name = "anotherCategory", schema = @Schema( implementation = Category.class, description = "prop schema 2" ) ) @SchemaProperty( name = "anotherInteger", schema = @Schema( type = "integer", description = "prop schema 1", format = "int32", maximum = "10" ) ) public class AnnotatedPet { private long id; private Category category; private String name; private List photoUrls = new ArrayList(); private List tags = new ArrayList(); private String status; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "category") public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElementWrapper(name = "photoUrls") @XmlElement(name = "photoUrl") public List getPhotoUrls() { return photoUrls; } public void setPhotoUrls(List photoUrls) { this.photoUrls = photoUrls; } @XmlElementWrapper(name = "tags") @XmlElement(name = "tag") public List getTags() { return tags; } public void setTags(List tags) { this.tags = tags; } @XmlElement(name = "status") @Schema(description = "pet status in the store", allowableValues = {"available", "pending", "sold"}) public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/AnnotatedPetSinglePatternProperty.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.PatternProperty; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.SchemaProperty; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import java.util.ArrayList; import java.util.List; @Schema(description = "Annotated Pet", nullable = true) @PatternProperty( regex = "what.*ever", schema = @Schema( type = "integer", description = "prop schema 1", format = "int32", maximum = "10" ) ) @SchemaProperty( name = "anotherCategory", schema = @Schema( implementation = Category.class, description = "prop schema 2" ) ) public class AnnotatedPetSinglePatternProperty { private long id; private Category category; private String name; private List photoUrls = new ArrayList(); private List tags = new ArrayList(); private String status; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "category") public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElementWrapper(name = "photoUrls") @XmlElement(name = "photoUrl") public List getPhotoUrls() { return photoUrls; } public void setPhotoUrls(List photoUrls) { this.photoUrls = photoUrls; } @XmlElementWrapper(name = "tags") @XmlElement(name = "tag") public List getTags() { return tags; } public void setTags(List tags) { this.tags = tags; } @XmlElement(name = "status") @Schema(description = "pet status in the store", allowableValues = {"available", "pending", "sold"}) public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/Category.java ================================================ package io.swagger.v3.core.resolving.v31.model; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Category") public class Category { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } public Category() { } public Category(String name) { this.name = name; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/Client.java ================================================ package io.swagger.v3.core.resolving.v31.model; public class Client { private String name; private int creditCard; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getCreditCard() { return creditCard; } public void setCreditCard(int creditCard) { this.creditCard = creditCard; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/CreditCard.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import java.util.Set; public class CreditCard { private String billingAddress; private Set acceptingCountries; private Set availableCurrencies; public String getBillingAddress() { return billingAddress; } public void setBillingAddress(String billingAddress) { this.billingAddress = billingAddress; } @ArraySchema(schema = @Schema(description = "accepting country")) public Set getAcceptingCountries() { return acceptingCountries; } public void setAcceptingCountries(Set acceptingCountries) { this.acceptingCountries = acceptingCountries; } @ArraySchema(schema = @Schema(description = "available currencies")) public Set getAvailableCurrencies() { return availableCurrencies; } public void setAvailableCurrencies(Set availableCurrencies) { this.availableCurrencies = availableCurrencies; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/Currency.java ================================================ package io.swagger.v3.core.resolving.v31.model; public class Currency { private String currencyCode; public String getCurrencyCode() { return currencyCode; } public void setCurrencyCode(String currencyCode) { this.currencyCode = currencyCode; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/CustomGenerator.java ================================================ package io.swagger.v3.core.resolving.v31.model; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerators; public class CustomGenerator extends ObjectIdGenerators.PropertyGenerator { private static final long serialVersionUID = 1L; protected CustomGenerator(Class scope) { super(scope); } @Override public ObjectIdGenerator forScope(Class scope) { return null; } @Override public ObjectIdGenerator newForSerialization(Object context) { return null; } @Override public IdKey key(Object key) { return null; } @Override public Object generateId(Object forPojo) { return null; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/ExtensionUser.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "User") @Schema( description = "User", extensions = { @Extension(name = "x-user", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "user-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) public class ExtensionUser { private long id; private String username; private String firstName; private String lastName; private String email; private String password; private String phone; private int userStatus; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "firstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement(name = "lastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone") public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @XmlElement(name = "userStatus") @Schema( description = "User Status", extensions = { @Extension(name = "x-userStatus", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "userStatus-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/JacksonBean.java ================================================ package io.swagger.v3.core.resolving.v31.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonValue; public class JacksonBean { private String id; private String ignored; private StringValueBean bean; private NotFoundModel model; private NotFoundModel model2; @JsonIgnore public String getIgnored() { return ignored; } public void setIgnored(String ignored) { this.ignored = ignored; } public void setId(String id) { this.id = id; } public void setModel(NotFoundModel model) { this.model = model; } public StringValueBean getBean() { return bean; } public void setBean(StringValueBean bean) { this.bean = bean; } @JsonProperty("identity") public String getId() { return id; } @JsonUnwrapped public NotFoundModel getModel() { return model; } @JsonUnwrapped(prefix = "pre", suffix = "suf") public NotFoundModel getModel2() { return model2; } public void setModel2(NotFoundModel model2) { this.model2 = model2; } public static class StringValueBean { private final String value; @JsonCreator public StringValueBean(String value) { this.value = value; } @JsonValue public String getValue() { return value; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/ListOfStringsBeanParam.java ================================================ package io.swagger.v3.core.resolving.v31.model; import javax.ws.rs.QueryParam; import java.util.List; public class ListOfStringsBeanParam { @QueryParam(value = "listOfStrings") private List list; public List getList() { return list; } public void setList(List list) { this.list = list; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/ModelWithDependentSchema.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.media.DependentSchema; import io.swagger.v3.oas.annotations.media.DependentSchemas; import io.swagger.v3.oas.annotations.media.Schema; @DependentSchemas( value = { @DependentSchema( name = "value", schema = @Schema( properties = { @StringToClassMapItem( key = "enable", value = ModelWithDependentSchema.BooleanFakeClass.class ) } ) ) } ) public class ModelWithDependentSchema { private String name; private int value; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } class BooleanFakeClass { private boolean type; public boolean isType() { return type; } public void setType(boolean type) { this.type = type; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/ModelWithJsonIdentity.java ================================================ package io.swagger.v3.core.resolving.v31.model; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.ObjectIdGenerators; public class ModelWithJsonIdentity { @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") @JsonProperty("PropertyGeneratorAsId") public SourceDefinition1 testPropertyGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") @JsonProperty("PropertyGeneratorAsProperty") public SourceDefinition1 testPropertyGeneratorAsProperty; public class SourceDefinition1 { public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "driverId") @JsonProperty("ChangedPropertyName") public SourceDefinition2 testChangedPropertyName; @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "driverId") @JsonProperty("ChangedPropertyName2") public SourceDefinition2 testChangedPropertyName2; static public class SourceDefinition2 { @JsonProperty("driverId") public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class) @JsonProperty("SourceWithoutPropertyAsId") public SourceDefinition3 testWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class) @JsonProperty("SourceWithoutPropertyAsProperty") public SourceDefinition3 testWithoutPropertyAsProperty; public class SourceDefinition3 { @JsonProperty("driverId") public String driver; public String name; @JsonProperty("@id") public String id; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "testName1") @JsonProperty("IntSequenceGeneratorAsId") public SourceDefinition4 testIntSequenceGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "testName2") @JsonProperty("IntSequenceGeneratorAsProperty") public SourceDefinition4 testIntSequenceGeneratorAsProperty; public class SourceDefinition4 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) @JsonProperty("IntSequenceWithoutPropertyAsId") public SourceDefinition5 testIntSequenceWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) @JsonProperty("IntSequenceWithoutPropertyAsProperty") public SourceDefinition5 testIntSequenceWithoutPropertyAsProperty; public class SourceDefinition5 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "UUID1") @JsonProperty("UUIDGeneratorAsId") public SourceDefinition6 testUUIDGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "UUID2") @JsonProperty("UUIDGeneratorAsProperty") public SourceDefinition6 testUUIDGeneratorAsProperty; public class SourceDefinition6 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class) @JsonProperty("UUIDGeneratorWithoutPropertyAsId") public SourceDefinition7 testUUIDGeneratorWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class) @JsonProperty("UUIDGeneratorWithoutPropertyAsProperty") public SourceDefinition7 testUUIDGeneratorWithoutPropertyAsProperty; public class SourceDefinition7 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.None.class, property = "testGeneratorsNone") @JsonProperty("GeneratorsNone") public SourceDefinition8 testGeneratorsNone; public class SourceDefinition8 { @JsonProperty("driverId") public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = CustomGenerator.class, property = "name") @JsonProperty("CustomGenerator") public SourceDefinition9 testCustomGenerator; public class SourceDefinition9 { public String driver; public String name; } @JsonIdentityInfo(generator = CustomGenerator.class, property = "name") @JsonProperty("WithoutJsonIdentityReference") public SourceDefinition10 testWithoutJsonIdentityReference; public class SourceDefinition10 { public String driver; public String name; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/ModelWithJsonIdentityCyclic.java ================================================ package io.swagger.v3.core.resolving.v31.model; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import java.util.List; public class ModelWithJsonIdentityCyclic { public Long id; public List sourceDefinitions; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") public static class SourceDefinition { public String driver; public String name; @JsonIdentityReference(alwaysAsId=true) @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public ModelWithJsonIdentityCyclic model; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/ModelWithOAS31Stuff.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; @Schema( $id = "http://yourdomain.com/schemas/myschema.json", description = "this is model for testing OAS 3.1 resolving", $comment = "Random comment at schema level", types = {"object"} ) public class ModelWithOAS31Stuff { private List randomList; private Object status; private int intValue; private String text; private String encodedString; private Address address; private Client client; @ArraySchema( schema = @Schema( types = { "string" }, description = "itemdescription", title = "itemtitle" ), arraySchema = @Schema(description = "arraydescription", title = "arraytitle"), maxContains = 10, minContains = 1, contains = @Schema( types = "string" ), unevaluatedItems = @Schema( types = "number" ), prefixItems = { @Schema( types = "string" ) } ) public List getRandomList() { return randomList; } public void setRandomList(List randomList) { this.randomList = randomList; } @Schema(types = { "string", "number" }) public Object getStatus() { return status; } public void setStatus(Object status) { this.status = status; } @Schema( $anchor = "intValue", $comment = "comment at schema property level", exclusiveMaximumValue = 100, exclusiveMinimumValue = 1 ) public int getIntValue() { return intValue; } public void setIntValue(int intValue) { this.intValue = intValue; } @Schema( contentEncoding = "plan/text", contentMediaType = "base64" ) public String getText() { return text; } public void setText(String text) { this.text = text; } @Schema( contentMediaType = "application/jwt", contentSchema = MultipleBaseBean.class ) public String getEncodedString() { return encodedString; } public void setEncodedString(String encodedString) { this.encodedString = encodedString; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Schema( dependentSchemas = { @StringToClassMapItem( key = "creditCard", value = CreditCard.class ) }, patternProperties = { @StringToClassMapItem( key = "creditCard", value = CreditCard.class ) }, properties = { @StringToClassMapItem( key = "extraObject", value = Object.class ) } ) public Client getClient() { return client; } public void setClient(Client client) { this.client = client; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/ModelWithOAS31StuffMinimal.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; @Schema( $id = "http://yourdomain.com/schemas/myschema.json", description = "this is model for testing OAS 3.1 resolving", $comment = "Random comment at schema level", types = {"object"} ) public class ModelWithOAS31StuffMinimal { private Addr address; public Addr getAddress() { return address; } public void setAddress(Addr address) { this.address = address; } public static class Addr { public String foo; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/MultipleBaseBean.java ================================================ package io.swagger.v3.core.resolving.v31.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleBaseBean", subTypes = { MultipleSub1Bean.class, MultipleSub2Bean.class } ) public class MultipleBaseBean { public String beanType; public int a; public String b; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/MultipleSub1Bean.java ================================================ package io.swagger.v3.core.resolving.v31.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleSub1Bean" ) public class MultipleSub1Bean extends MultipleBaseBean { public int c; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/MultipleSub2Bean.java ================================================ package io.swagger.v3.core.resolving.v31.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleSub2Bean" ) public class MultipleSub2Bean extends MultipleBaseBean { public int d; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/NotFoundModel.java ================================================ package io.swagger.v3.core.resolving.v31.model; public class NotFoundModel { int code; String message; public NotFoundModel() { } public NotFoundModel(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/Pet.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.util.ArrayList; import java.util.List; @XmlRootElement(name = "Pet") public class Pet { private long id; private Category category; private String name; private List photoUrls = new ArrayList(); private List tags = new ArrayList(); private String status; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "category") public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElementWrapper(name = "photoUrls") @XmlElement(name = "photoUrl") public List getPhotoUrls() { return photoUrls; } public void setPhotoUrls(List photoUrls) { this.photoUrls = photoUrls; } @XmlElementWrapper(name = "tags") @XmlElement(name = "tag") public List getTags() { return tags; } public void setTags(List tags) { this.tags = tags; } @XmlElement(name = "status") @Schema(description = "pet status in the store", allowableValues = {"available", "pending", "sold"}) public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/PostalCodeNumberPattern.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.Schema; public class PostalCodeNumberPattern { private Object postalCode; @Schema( pattern = "[0-9]{5}(-[0-9]{4})?", type = "string" ) public Object getPostalCode() { return postalCode; } public void setPostalCode(Object postalCode) { this.postalCode = postalCode; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/PostalCodePattern.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.Schema; public class PostalCodePattern { private Object postalCode; @Schema( pattern = "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]", type = "string" ) public Object getPostalCode() { return postalCode; } public void setPostalCode(Object postalCode) { this.postalCode = postalCode; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/Tag.java ================================================ package io.swagger.v3.core.resolving.v31.model; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Tag") public class Tag { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/User.java ================================================ package io.swagger.v3.core.resolving.v31.model; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "User") public class User { private long id; private String username; private String firstName; private String lastName; private String email; private String password; private String phone; private int userStatus; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "firstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement(name = "lastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone") public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @XmlElement(name = "userStatus") @Schema(description = "User Status") //, allowableValues = {"1","2","3"}) public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/siblings/Category.java ================================================ package io.swagger.v3.core.resolving.v31.model.siblings; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "parent") public class Category { private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/model/siblings/Pet.java ================================================ package io.swagger.v3.core.resolving.v31.model.siblings; import io.swagger.v3.oas.annotations.media.Schema; public class Pet { private Category category; @Schema(description = "child") public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/roundtrip/ComprehensiveRoundTripTest.java ================================================ package io.swagger.v3.core.roundtrip; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.JsonAssert; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.media.Discriminator; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import org.testng.annotations.Test; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; /** * Comprehensive tests for round-trip (serialization + deserialization) of OpenAPI 3.0 and 3.1 documents. * This test class covers various scenarios, edge cases, and combinations of OpenAPI elements. */ public class ComprehensiveRoundTripTest { /** * Test round-trip of OpenAPI 3.0 document with JSON */ @Test public void testRoundTrip30Json() throws IOException { // Create a simple OpenAPI 3.0 document OpenAPI originalOpenAPI = createBasicOpenAPI30(); // Serialize to JSON String json = Json.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Json.mapper().readValue(json, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI); assertEquals(deserializedOpenAPI.getOpenapi(), "3.0.1"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), "Test API"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), "1.0.0"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths()); assertTrue(deserializedOpenAPI.getPaths().containsKey("/test")); // Verify components assertNotNull(deserializedOpenAPI.getComponents()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas()); assertTrue(deserializedOpenAPI.getComponents().getSchemas().containsKey("TestSchema")); // Serialize again String jsonAgain = Json.pretty(deserializedOpenAPI); // Compare JSON strings JsonAssert.assertJsonEquals(Json.mapper(), json, jsonAgain, "JSON round-trip failed"); } /** * Test round-trip of OpenAPI 3.0 document with YAML */ @Test public void testRoundTrip30Yaml() throws IOException { // Create a simple OpenAPI 3.0 document OpenAPI originalOpenAPI = createBasicOpenAPI30(); // Serialize to YAML String yaml = Yaml.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Yaml.mapper().readValue(yaml, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI); assertEquals(deserializedOpenAPI.getOpenapi(), "3.0.1"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), "Test API"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), "1.0.0"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths()); assertTrue(deserializedOpenAPI.getPaths().containsKey("/test")); // Verify components assertNotNull(deserializedOpenAPI.getComponents()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas()); assertTrue(deserializedOpenAPI.getComponents().getSchemas().containsKey("TestSchema")); // Serialize again String yamlAgain = Yaml.pretty(deserializedOpenAPI); // Compare YAML strings JsonAssert.assertJsonEquals(Yaml.mapper(), yaml, yamlAgain, "YAML round-trip failed"); } /** * Test round-trip of OpenAPI 3.1 document with JSON */ @Test public void testRoundTrip31Json() throws IOException { // Create a simple OpenAPI 3.1 document OpenAPI originalOpenAPI = createBasicOpenAPI31(); // Serialize to JSON String json = Json31.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI); assertEquals(deserializedOpenAPI.getOpenapi(), "3.1.0"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), "Test API"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), "1.0.0"); assertEquals(deserializedOpenAPI.getInfo().getSummary(), "Test API Summary"); assertEquals(deserializedOpenAPI.getInfo().getLicense().getIdentifier(), "MIT"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths()); assertTrue(deserializedOpenAPI.getPaths().containsKey("/test")); // Verify components assertNotNull(deserializedOpenAPI.getComponents()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas()); assertTrue(deserializedOpenAPI.getComponents().getSchemas().containsKey("TestSchema")); // Verify webhooks assertNotNull(deserializedOpenAPI.getWebhooks()); assertTrue(deserializedOpenAPI.getWebhooks().containsKey("testWebhook")); // Serialize again String jsonAgain = Json31.pretty(deserializedOpenAPI); // Compare JSON strings JsonAssert.assertJsonEquals(Json31.mapper(), json, jsonAgain, "JSON round-trip failed"); } /** * Test round-trip of OpenAPI 3.1 document with YAML */ @Test public void testRoundTrip31Yaml() throws IOException { // Create a simple OpenAPI 3.1 document OpenAPI originalOpenAPI = createBasicOpenAPI31(); // Serialize to YAML String yaml = Yaml31.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Yaml31.mapper().readValue(yaml, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI); assertEquals(deserializedOpenAPI.getOpenapi(), "3.1.0"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), "Test API"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), "1.0.0"); assertEquals(deserializedOpenAPI.getInfo().getSummary(), "Test API Summary"); assertEquals(deserializedOpenAPI.getInfo().getLicense().getIdentifier(), "MIT"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths()); assertTrue(deserializedOpenAPI.getPaths().containsKey("/test")); // Verify components assertNotNull(deserializedOpenAPI.getComponents()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas()); assertTrue(deserializedOpenAPI.getComponents().getSchemas().containsKey("TestSchema")); // Verify webhooks assertNotNull(deserializedOpenAPI.getWebhooks()); assertTrue(deserializedOpenAPI.getWebhooks().containsKey("testWebhook")); // Serialize again String yamlAgain = Yaml31.pretty(deserializedOpenAPI); // Compare YAML strings JsonAssert.assertJsonEquals(Yaml31.mapper(), yaml, yamlAgain, "YAML round-trip failed"); } /** * Test round-trip of OpenAPI 3.1 document with complex structures */ @Test public void testComplexRoundTrip31() throws IOException { // Create an OpenAPI 3.1 document with complex structures OpenAPI originalOpenAPI = createComplexOpenAPI31(); // Serialize to JSON String json = Json31.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify complex structures // Verify discriminator extensions assertNotNull(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getDiscriminator()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getDiscriminator().getExtensions()); assertEquals(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getDiscriminator().getExtensions().get("x-test-extension"), "test-value"); // Verify component path items assertNotNull(deserializedOpenAPI.getComponents().getPathItems()); assertTrue(deserializedOpenAPI.getComponents().getPathItems().containsKey("/testPathItem")); assertEquals(deserializedOpenAPI.getComponents().getPathItems().get("/testPathItem").getDescription(), "Test path item"); assertEquals(deserializedOpenAPI.getComponents().getPathItems().get("/testPathItem").getSummary(), "Test path item summary"); assertNotNull(deserializedOpenAPI.getComponents().getPathItems().get("/testPathItem").getGet()); assertEquals(deserializedOpenAPI.getComponents().getPathItems().get("/testPathItem").getGet().getOperationId(), "getTest"); // Verify path item refs and siblings assertEquals(deserializedOpenAPI.getPaths().get("/refTest").get$ref(), "#/components/pathItems/testPathItem"); assertEquals(deserializedOpenAPI.getPaths().get("/refTest").getDescription(), "Ref path item description"); assertEquals(deserializedOpenAPI.getPaths().get("/refTest").getSummary(), "Ref path item summary"); // Verify parameter refs and siblings assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(0).get$ref(), "#/components/parameters/testParameter"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(0).getDescription(), "Ref parameter description"); // Verify example refs and siblings assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(1).getName(), "testParam"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(1).getIn(), "query"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(1).getExamples().get("refExample").get$ref(), "#/components/examples/testExample"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(1).getExamples().get("refExample").getSummary(), "Ref example summary"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(1).getExamples().get("refExample").getDescription(), "Ref example description"); // Serialize again String jsonAgain = Json31.pretty(deserializedOpenAPI); // Compare JSON strings JsonAssert.assertJsonEquals(Json31.mapper(), json, jsonAgain, "JSON round-trip failed"); } /** * Test round-trip of OpenAPI 3.1 document with boolean schema */ @Test public void testBooleanSchemaRoundTrip() throws IOException { // Create an OpenAPI 3.1 document with boolean schema OpenAPI originalOpenAPI = createBasicOpenAPI31(); // Add boolean schema Schema booleanSchema = new Schema().booleanSchemaValue(true); originalOpenAPI.getComponents().getSchemas().put("BooleanSchema", booleanSchema); // Serialize to JSON String json = Json31.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify boolean schema assertTrue(Boolean.TRUE.equals(deserializedOpenAPI.getComponents().getSchemas().get("BooleanSchema").getBooleanSchemaValue())); // Verify that the schema is serialized as a boolean value ObjectMapper mapper = new ObjectMapper(); JsonNode jsonNode = mapper.readTree(json); assertTrue(jsonNode.get("components").get("schemas").get("BooleanSchema").isBoolean()); assertTrue(jsonNode.get("components").get("schemas").get("BooleanSchema").asBoolean()); // Serialize again String jsonAgain = Json31.pretty(deserializedOpenAPI); // Compare JSON strings JsonAssert.assertJsonEquals(Json.mapper(), json, jsonAgain, "JSON round-trip failed"); } /** * Test round-trip of OpenAPI 3.1 document with null values */ @Test public void testNullValuesRoundTrip() throws IOException { // Create an OpenAPI 3.1 document with null values OpenAPI originalOpenAPI = createBasicOpenAPI31(); // Add schema with null example Schema schema = originalOpenAPI.getComponents().getSchemas().get("TestSchema"); schema.setExample(null); schema.setExampleSetFlag(true); // Serialize to JSON String json = Json31.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify null values assertNotNull(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema")); assertEquals(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getExample(), null); assertTrue(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getExampleSetFlag()); // Serialize again String jsonAgain = Json31.pretty(deserializedOpenAPI); // Compare JSON strings JsonAssert.assertJsonEquals(Json.mapper(), json, jsonAgain, "JSON round-trip failed"); } /** * Test round-trip of real-world OpenAPI 3.1 document */ @Test public void testRealWorldRoundTrip31() throws IOException { // Load a real-world OpenAPI 3.1 document final String yaml = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/petstore-3.1_sample.yaml"); final OpenAPI originalOpenAPI = Yaml31.mapper().readValue(yaml, OpenAPI.class); // Serialize to YAML String serializedYaml = Yaml31.pretty(originalOpenAPI); // Deserialize back OpenAPI deserializedOpenAPI = Yaml31.mapper().readValue(serializedYaml, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI); assertEquals(deserializedOpenAPI.getOpenapi(), "3.1.0"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), "Swagger Petstore"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), "1.0.0"); assertEquals(deserializedOpenAPI.getInfo().getSummary(), "petstore sample for OAS 3.1.0"); assertEquals(deserializedOpenAPI.getInfo().getLicense().getName(), "MIT"); assertEquals(deserializedOpenAPI.getInfo().getLicense().getIdentifier(), "test"); // Verify webhooks assertNotNull(deserializedOpenAPI.getWebhooks()); assertNotNull(deserializedOpenAPI.getWebhooks().get("newPet")); assertNotNull(deserializedOpenAPI.getWebhooks().get("newPet").getPost()); // Verify component path items assertNotNull(deserializedOpenAPI.getComponents().getPathItems()); assertNotNull(deserializedOpenAPI.getComponents().getPathItems().get("/pet")); assertEquals(deserializedOpenAPI.getComponents().getPathItems().get("/pet").getDescription(), "get a pet"); assertNotNull(deserializedOpenAPI.getComponents().getPathItems().get("/pet").getGet()); assertEquals(deserializedOpenAPI.getComponents().getPathItems().get("/pet").getGet().getOperationId(), "getPet"); // Serialize again String yamlAgain = Yaml31.pretty(deserializedOpenAPI); // Compare YAML strings (normalize whitespace) JsonAssert.assertJsonEquals(Yaml31.mapper(), serializedYaml, yamlAgain, "YAML round-trip failed"); } /** * Helper method to create a basic OpenAPI 3.0 document */ private OpenAPI createBasicOpenAPI30() { OpenAPI openAPI = new OpenAPI(); openAPI.setOpenapi("3.0.1"); // Add info Info info = new Info() .title("Test API") .version("1.0.0") .description("Test API Description") .contact(new Contact().name("Test Contact").email("test@example.com")) .license(new License().name("MIT")); openAPI.setInfo(info); // Add paths Paths paths = new Paths(); PathItem pathItem = new PathItem(); // Add GET operation Operation getOperation = new Operation() .operationId("getTest") .summary("Get Test") .description("Get Test Description"); // Add responses ApiResponses responses = new ApiResponses(); ApiResponse response = new ApiResponse() .description("Successful response"); responses.addApiResponse("200", response); getOperation.setResponses(responses); pathItem.setGet(getOperation); paths.addPathItem("/test", pathItem); openAPI.setPaths(paths); // Add components Components components = new Components(); Schema schema = new Schema() .type("object") .title("TestSchema") .description("Test Schema Description"); components.addSchemas("TestSchema", schema); openAPI.setComponents(components); return openAPI; } /** * Helper method to create a basic OpenAPI 3.1 document */ private OpenAPI createBasicOpenAPI31() { OpenAPI openAPI = new OpenAPI(); openAPI.setOpenapi("3.1.0"); // Add info Info info = new Info() .title("Test API") .version("1.0.0") .description("Test API Description") .summary("Test API Summary") .contact(new Contact().name("Test Contact").email("test@example.com")) .license(new License().name("MIT").identifier("MIT")); openAPI.setInfo(info); // Add paths Paths paths = new Paths(); PathItem pathItem = new PathItem(); // Add GET operation Operation getOperation = new Operation() .operationId("getTest") .summary("Get Test") .description("Get Test Description"); // Add responses ApiResponses responses = new ApiResponses(); ApiResponse response = new ApiResponse() .description("Successful response"); responses.addApiResponse("200", response); getOperation.setResponses(responses); pathItem.setGet(getOperation); paths.addPathItem("/test", pathItem); openAPI.setPaths(paths); // Add components Components components = new Components(); Schema schema = new Schema() .type("object") .title("TestSchema") .description("Test Schema Description"); components.addSchemas("TestSchema", schema); openAPI.setComponents(components); // Add webhooks Map webhooks = new HashMap<>(); PathItem webhookPathItem = new PathItem(); Operation postOperation = new Operation() .operationId("postWebhook") .summary("Post Webhook") .description("Post Webhook Description"); webhookPathItem.setPost(postOperation); webhooks.put("testWebhook", webhookPathItem); openAPI.setWebhooks(webhooks); return openAPI; } /** * Helper method to create a complex OpenAPI 3.1 document */ private OpenAPI createComplexOpenAPI31() { OpenAPI openAPI = createBasicOpenAPI31(); // Add discriminator with extensions Schema schema = openAPI.getComponents().getSchemas().get("TestSchema"); Discriminator discriminator = new Discriminator().propertyName("type"); Map extensions = new HashMap<>(); extensions.put("x-test-extension", "test-value"); discriminator.setExtensions(extensions); schema.setDiscriminator(discriminator); // Add component path items PathItem pathItem = new PathItem() .description("Test path item") .summary("Test path item summary"); pathItem.setGet(new Operation().operationId("getTest")); openAPI.getComponents().pathItems(new HashMap<>()); openAPI.getComponents().getPathItems().put("/testPathItem", pathItem); // Add path with reference and siblings PathItem refPathItem = new PathItem() .$ref("#/components/pathItems/testPathItem") .description("Ref path item description") .summary("Ref path item summary"); openAPI.getPaths().put("/refTest", refPathItem); // Add component parameters Parameter parameter = new Parameter() .name("testParam") .in("query") .description("Test parameter"); openAPI.getComponents().parameters(new HashMap<>()); openAPI.getComponents().getParameters().put("testParameter", parameter); // Add operation with parameter reference and siblings Parameter refParameter = new Parameter() .$ref("#/components/parameters/testParameter") .description("Ref parameter description"); openAPI.getPaths().get("/test").getGet().addParametersItem(refParameter); // Add component examples Example example = new Example() .summary("Test example summary") .description("Test example description") .value("Test example value"); openAPI.getComponents().examples(new HashMap<>()); openAPI.getComponents().getExamples().put("testExample", example); // Add parameter with example reference and siblings Parameter paramWithExample = new Parameter() .name("testParam") .in("query") .description("Test parameter"); Example refExample = new Example() .$ref("#/components/examples/testExample") .summary("Ref example summary") .description("Ref example description"); paramWithExample.examples(new HashMap<>()); paramWithExample.getExamples().put("refExample", refExample); openAPI.getPaths().get("/test").getGet().addParametersItem(paramWithExample); return openAPI; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/ComprehensiveSerializationTest.java ================================================ package io.swagger.v3.core.serialization; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.media.Discriminator; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.examples.Example; import org.testng.annotations.Test; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; /** * Comprehensive tests for serialization of OpenAPI 3.0 and 3.1 documents. * This test class covers various scenarios, edge cases, and combinations of OpenAPI elements. */ public class ComprehensiveSerializationTest { /** * Test basic serialization of OpenAPI 3.0 document to JSON */ @Test public void testBasicSerialization30Json() throws IOException { // Create a simple OpenAPI 3.0 document OpenAPI openAPI = createBasicOpenAPI30(); // Serialize to JSON String json = Json.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Json.mapper().readValue(json, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI); assertEquals(deserializedOpenAPI.getOpenapi(), "3.0.1"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), "Test API"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), "1.0.0"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths()); assertTrue(deserializedOpenAPI.getPaths().containsKey("/test")); // Verify components assertNotNull(deserializedOpenAPI.getComponents()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas()); assertTrue(deserializedOpenAPI.getComponents().getSchemas().containsKey("TestSchema")); } /** * Test basic serialization of OpenAPI 3.0 document to YAML */ @Test public void testBasicSerialization30Yaml() throws IOException { // Create a simple OpenAPI 3.0 document OpenAPI openAPI = createBasicOpenAPI30(); // Serialize to YAML String yaml = Yaml.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Yaml.mapper().readValue(yaml, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI); assertEquals(deserializedOpenAPI.getOpenapi(), "3.0.1"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), "Test API"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), "1.0.0"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths()); assertTrue(deserializedOpenAPI.getPaths().containsKey("/test")); // Verify components assertNotNull(deserializedOpenAPI.getComponents()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas()); assertTrue(deserializedOpenAPI.getComponents().getSchemas().containsKey("TestSchema")); } /** * Test basic serialization of OpenAPI 3.1 document to JSON */ @Test public void testBasicSerialization31Json() throws IOException { // Create a simple OpenAPI 3.1 document OpenAPI openAPI = createBasicOpenAPI31(); // Serialize to JSON String json = Json31.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI); assertEquals(deserializedOpenAPI.getOpenapi(), "3.1.0"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), "Test API"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), "1.0.0"); assertEquals(deserializedOpenAPI.getInfo().getSummary(), "Test API Summary"); assertEquals(deserializedOpenAPI.getInfo().getLicense().getIdentifier(), "MIT"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths()); assertTrue(deserializedOpenAPI.getPaths().containsKey("/test")); // Verify components assertNotNull(deserializedOpenAPI.getComponents()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas()); assertTrue(deserializedOpenAPI.getComponents().getSchemas().containsKey("TestSchema")); // Verify webhooks assertNotNull(deserializedOpenAPI.getWebhooks()); assertTrue(deserializedOpenAPI.getWebhooks().containsKey("testWebhook")); } /** * Test basic serialization of OpenAPI 3.1 document to YAML */ @Test public void testBasicSerialization31Yaml() throws IOException { // Create a simple OpenAPI 3.1 document OpenAPI openAPI = createBasicOpenAPI31(); // Serialize to YAML String yaml = Yaml31.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Yaml31.mapper().readValue(yaml, OpenAPI.class); // Verify basic structure assertNotNull(deserializedOpenAPI); assertEquals(deserializedOpenAPI.getOpenapi(), "3.1.0"); assertEquals(deserializedOpenAPI.getInfo().getTitle(), "Test API"); assertEquals(deserializedOpenAPI.getInfo().getVersion(), "1.0.0"); assertEquals(deserializedOpenAPI.getInfo().getSummary(), "Test API Summary"); assertEquals(deserializedOpenAPI.getInfo().getLicense().getIdentifier(), "MIT"); // Verify paths assertNotNull(deserializedOpenAPI.getPaths()); assertTrue(deserializedOpenAPI.getPaths().containsKey("/test")); // Verify components assertNotNull(deserializedOpenAPI.getComponents()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas()); assertTrue(deserializedOpenAPI.getComponents().getSchemas().containsKey("TestSchema")); // Verify webhooks assertNotNull(deserializedOpenAPI.getWebhooks()); assertTrue(deserializedOpenAPI.getWebhooks().containsKey("testWebhook")); } /** * Test serialization of OpenAPI 3.1 document with component path items */ @Test public void testComponentPathItemsSerialization() throws IOException { // Create an OpenAPI 3.1 document with component path items OpenAPI openAPI = createBasicOpenAPI31(); // Add component path items PathItem pathItem = new PathItem() .description("Test path item") .summary("Test path item summary"); pathItem.setGet(new Operation().operationId("getTest")); openAPI.getComponents().pathItems(new HashMap<>()); openAPI.getComponents().getPathItems().put("/testPathItem", pathItem); // Serialize to JSON String json = Json31.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify component path items assertNotNull(deserializedOpenAPI.getComponents().getPathItems()); assertTrue(deserializedOpenAPI.getComponents().getPathItems().containsKey("/testPathItem")); assertEquals(deserializedOpenAPI.getComponents().getPathItems().get("/testPathItem").getDescription(), "Test path item"); assertEquals(deserializedOpenAPI.getComponents().getPathItems().get("/testPathItem").getSummary(), "Test path item summary"); assertNotNull(deserializedOpenAPI.getComponents().getPathItems().get("/testPathItem").getGet()); assertEquals(deserializedOpenAPI.getComponents().getPathItems().get("/testPathItem").getGet().getOperationId(), "getTest"); } /** * Test serialization of OpenAPI 3.1 document with discriminator extensions */ @Test public void testDiscriminatorExtensionsSerialization() throws IOException { // Create an OpenAPI 3.1 document with discriminator extensions OpenAPI openAPI = createBasicOpenAPI31(); // Add discriminator with extensions Schema schema = openAPI.getComponents().getSchemas().get("TestSchema"); Discriminator discriminator = new Discriminator().propertyName("type"); Map extensions = new HashMap<>(); extensions.put("x-test-extension", "test-value"); discriminator.setExtensions(extensions); schema.setDiscriminator(discriminator); // Serialize to JSON String json = Json31.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify discriminator extensions assertNotNull(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getDiscriminator()); assertNotNull(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getDiscriminator().getExtensions()); assertEquals(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getDiscriminator().getExtensions().get("x-test-extension"), "test-value"); } /** * Test serialization of OpenAPI 3.1 document with path item references and siblings */ @Test public void testPathItemRefsAndSiblingsSerialization() throws IOException { // Create an OpenAPI 3.1 document with path item references and siblings OpenAPI openAPI = createBasicOpenAPI31(); // Add component path items PathItem pathItem = new PathItem() .description("Test path item") .summary("Test path item summary"); pathItem.setGet(new Operation().operationId("getTest")); openAPI.getComponents().pathItems(new HashMap<>()); openAPI.getComponents().getPathItems().put("testPathItem", pathItem); // Add path with reference and siblings PathItem refPathItem = new PathItem() .$ref("#/components/pathItems/testPathItem") .description("Ref path item description") .summary("Ref path item summary"); openAPI.getPaths().put("/refTest", refPathItem); // Serialize to JSON String json = Json31.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify path item refs and siblings assertEquals(deserializedOpenAPI.getPaths().get("/refTest").get$ref(), "#/components/pathItems/testPathItem"); assertEquals(deserializedOpenAPI.getPaths().get("/refTest").getDescription(), "Ref path item description"); assertEquals(deserializedOpenAPI.getPaths().get("/refTest").getSummary(), "Ref path item summary"); } /** * Test serialization of OpenAPI 3.1 document with parameter references and siblings */ @Test public void testParameterRefsAndSiblingsSerialization() throws IOException { // Create an OpenAPI 3.1 document with parameter references and siblings OpenAPI openAPI = createBasicOpenAPI31(); // Add component parameters Parameter parameter = new Parameter() .name("testParam") .in("query") .description("Test parameter"); openAPI.getComponents().parameters(new HashMap<>()); openAPI.getComponents().getParameters().put("testParameter", parameter); // Add operation with parameter reference and siblings Parameter refParameter = new Parameter() .$ref("#/components/parameters/testParameter") .description("Ref parameter description"); openAPI.getPaths().get("/test").getGet().addParametersItem(refParameter); // Serialize to JSON String json = Json31.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify parameter refs and siblings assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(0).get$ref(), "#/components/parameters/testParameter"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(0).getDescription(), "Ref parameter description"); } /** * Test serialization of OpenAPI 3.1 document with example references and siblings */ @Test public void testExampleRefsAndSiblingsSerialization() throws IOException { // Create an OpenAPI 3.1 document with example references and siblings OpenAPI openAPI = createBasicOpenAPI31(); // Add component examples Example example = new Example() .summary("Test example summary") .description("Test example description") .value("Test example value"); openAPI.getComponents().examples(new HashMap<>()); openAPI.getComponents().getExamples().put("testExample", example); // Add parameter with example reference and siblings Parameter parameter = new Parameter() .name("testParam") .in("query") .description("Test parameter"); Example refExample = new Example() .$ref("#/components/examples/testExample") .summary("Ref example summary") .description("Ref example description"); parameter.examples(new HashMap<>()); parameter.getExamples().put("refExample", refExample); openAPI.getPaths().get("/test").getGet().addParametersItem(parameter); // Serialize to JSON String json = Json31.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify example refs and siblings assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(0).getName(), "testParam"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(0).getIn(), "query"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(0).getExamples().get("refExample").get$ref(), "#/components/examples/testExample"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(0).getExamples().get("refExample").getSummary(), "Ref example summary"); assertEquals(deserializedOpenAPI.getPaths().get("/test").getGet().getParameters().get(0).getExamples().get("refExample").getDescription(), "Ref example description"); } /** * Test serialization of OpenAPI 3.1 document with boolean schema */ @Test public void testBooleanSchemaSerialization() throws IOException { // Create an OpenAPI 3.1 document with boolean schema OpenAPI openAPI = createBasicOpenAPI31(); // Add boolean schema Schema booleanSchema = new Schema().booleanSchemaValue(true); openAPI.getComponents().getSchemas().put("BooleanSchema", booleanSchema); // Serialize to JSON String json = Json31.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify boolean schema assertTrue(Boolean.TRUE.equals(deserializedOpenAPI.getComponents().getSchemas().get("BooleanSchema").getBooleanSchemaValue())); // Verify that the schema is serialized as a boolean value ObjectMapper mapper = new ObjectMapper(); JsonNode jsonNode = mapper.readTree(json); assertTrue(jsonNode.get("components").get("schemas").get("BooleanSchema").isBoolean()); assertTrue(jsonNode.get("components").get("schemas").get("BooleanSchema").asBoolean()); } /** * Test serialization of OpenAPI 3.1 document with null values */ @Test public void testNullValuesSerialization() throws IOException { // Create an OpenAPI 3.1 document with null values OpenAPI openAPI = createBasicOpenAPI31(); // Add schema with null example Schema schema = openAPI.getComponents().getSchemas().get("TestSchema"); schema.setExample(null); schema.setExampleSetFlag(true); // Serialize to JSON String json = Json31.pretty(openAPI); // Deserialize back to verify OpenAPI deserializedOpenAPI = Json31.mapper().readValue(json, OpenAPI.class); // Verify null values assertNotNull(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema")); assertEquals(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getExample(), null); assertTrue(deserializedOpenAPI.getComponents().getSchemas().get("TestSchema").getExampleSetFlag()); } /** * Helper method to create a basic OpenAPI 3.0 document */ private OpenAPI createBasicOpenAPI30() { OpenAPI openAPI = new OpenAPI(); openAPI.setOpenapi("3.0.1"); // Add info Info info = new Info() .title("Test API") .version("1.0.0") .description("Test API Description") .contact(new Contact().name("Test Contact").email("test@example.com")) .license(new License().name("MIT")); openAPI.setInfo(info); // Add paths Paths paths = new Paths(); PathItem pathItem = new PathItem(); // Add GET operation Operation getOperation = new Operation() .operationId("getTest") .summary("Get Test") .description("Get Test Description"); // Add responses ApiResponses responses = new ApiResponses(); ApiResponse response = new ApiResponse() .description("Successful response"); responses.addApiResponse("200", response); getOperation.setResponses(responses); pathItem.setGet(getOperation); paths.addPathItem("/test", pathItem); openAPI.setPaths(paths); // Add components Components components = new Components(); Schema schema = new Schema() .type("object") .title("TestSchema") .description("Test Schema Description"); components.addSchemas("TestSchema", schema); openAPI.setComponents(components); return openAPI; } /** * Helper method to create a basic OpenAPI 3.1 document */ private OpenAPI createBasicOpenAPI31() { OpenAPI openAPI = new OpenAPI(); openAPI.setOpenapi("3.1.0"); // Add info Info info = new Info() .title("Test API") .version("1.0.0") .description("Test API Description") .summary("Test API Summary") .contact(new Contact().name("Test Contact").email("test@example.com")) .license(new License().name("MIT").identifier("MIT")); openAPI.setInfo(info); // Add paths Paths paths = new Paths(); PathItem pathItem = new PathItem(); // Add GET operation Operation getOperation = new Operation() .operationId("getTest") .summary("Get Test") .description("Get Test Description"); // Add responses ApiResponses responses = new ApiResponses(); ApiResponse response = new ApiResponse() .description("Successful response"); responses.addApiResponse("200", response); getOperation.setResponses(responses); pathItem.setGet(getOperation); paths.addPathItem("/test", pathItem); openAPI.setPaths(paths); // Add components Components components = new Components(); Schema schema = new Schema() .type("object") .title("TestSchema") .description("Test Schema Description"); components.addSchemas("TestSchema", schema); openAPI.setComponents(components); // Add webhooks Map webhooks = new HashMap<>(); PathItem webhookPathItem = new PathItem(); Operation postOperation = new Operation() .operationId("postWebhook") .summary("Post Webhook") .description("Post Webhook Description"); webhookPathItem.setPost(postOperation); webhooks.put("testWebhook", webhookPathItem); openAPI.setWebhooks(webhooks); return openAPI; } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/JsonSerializationTest.java ================================================ package io.swagger.v3.core.serialization; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.dataformat.yaml.JacksonYAMLParseException; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.ObjectMapperFactory; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.servers.Server; import org.testng.annotations.Test; import org.yaml.snakeyaml.LoaderOptions; import java.util.HashMap; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; public class JsonSerializationTest { @Test public void testSerializeASpecWithPathReferences() throws Exception { OpenAPI swagger = new OpenAPI() .addServersItem(new Server().url("http://petstore.swagger.io")); PathItem expectedPath = new PathItem().$ref("http://my.company.com/paths/health.json"); swagger.path("/health", expectedPath); String swaggerJson = Json.mapper().writeValueAsString(swagger); OpenAPI rebuilt = Json.mapper().readValue(swaggerJson, OpenAPI.class); final PathItem path = rebuilt.getPaths().get("/health"); assertEquals(path, expectedPath); } @Test public void testExtension() throws Exception { OpenAPI swagger = new OpenAPI(); swagger.addExtension("x-foo-bar", "foo bar"); swagger.setInfo(new Info()); swagger.getInfo().addExtension("x-foo-bar", "foo bar"); String swaggerJson = Json.mapper().writeValueAsString(swagger); assertFalse(swaggerJson.contains("extensions")); OpenAPI rebuilt = Json.mapper().readValue(swaggerJson, OpenAPI.class); assertEquals(rebuilt.getExtensions().values().iterator().next(), "foo bar"); assertEquals(rebuilt.getInfo().getExtensions().values().iterator().next(), "foo bar"); } @Test public void testExtensionObjectWithProperties() throws Exception { final Map extensionObjectProps = new HashMap<>(); extensionObjectProps.put("x-foo-bar", "foo bar"); extensionObjectProps.put("x-bar-foo", null); OpenAPI swagger = new OpenAPI(); swagger.addExtension("x-extension-with-properties", extensionObjectProps); String swaggerJson = Json.mapper().writeValueAsString(swagger); assertEquals(swaggerJson, "{\"openapi\":\"3.0.1\",\"x-extension-with-properties\":{\"x-foo-bar\":\"foo bar\",\"x-bar-foo\":null}}"); } @Test public void testSerializeASpecWithResponseReferences() throws Exception { OpenAPI swagger = new OpenAPI() .addServersItem(new Server().url("http://petstore.swagger.io")); ApiResponse expectedResponse = new ApiResponse().$ref("http://my.company.com/paths/health.json"); PathItem expectedPath = new PathItem() .get( new Operation().responses( new ApiResponses() .addApiResponse("200", expectedResponse))); swagger.path("/health", expectedPath); String swaggerJson = Json.mapper().writeValueAsString(swagger); OpenAPI rebuilt = Json.mapper().readValue(swaggerJson, OpenAPI.class); assertEquals(rebuilt.getPaths().get("/health").getGet().getResponses().get("200"), expectedResponse); } @Test public void testSerializeNullExample() throws Exception { final String yaml = ResourceUtils.loadClassResource(getClass(), "specFiles/null-example.yaml"); OpenAPI deser = Yaml.mapper().readValue(yaml, OpenAPI.class); SerializationMatchers.assertEqualsToYaml(deser, yaml); } @Test public void testSerializeNullInSchemaExample() throws Exception { final String yaml = ResourceUtils.loadClassResource(getClass(), "specFiles/null-in-schema-example.yaml"); OpenAPI deser = Yaml.mapper().readValue(yaml, OpenAPI.class); SerializationMatchers.assertEqualsToYaml(deser, yaml); } @Test public void testSerializeJSONWithCustomFactory() throws Exception { // given JsonFactory jsonFactory = new JsonFactory(); final String json = ResourceUtils.loadClassResource(getClass(), "specFiles/petstore-3.0.json"); final String expectedJson = ResourceUtils.loadClassResource(getClass(), "specFiles/jsonSerialization-expected-petstore-3.0.json"); // when OpenAPI deser = ObjectMapperFactory.createJson(jsonFactory).readValue(json, OpenAPI.class); // then SerializationMatchers.assertEqualsToJson(deser, expectedJson); } @Test public void testSerializeYAMLWithCustomFactory() throws Exception { // given LoaderOptions loaderOptions = new LoaderOptions(); loaderOptions.setCodePointLimit(5 * 1024 * 1024); YAMLFactory yamlFactory = YAMLFactory.builder() .loaderOptions(loaderOptions) .build(); final String yaml = ResourceUtils.loadClassResource(getClass(), "specFiles/null-example.yaml"); // when OpenAPI deser = ObjectMapperFactory.createYaml(yamlFactory).readValue(yaml, OpenAPI.class); // then SerializationMatchers.assertEqualsToYaml(deser, yaml); } @Test(expectedExceptions = JacksonYAMLParseException.class) public void testSerializeYAMLWithCustomFactoryAndCodePointLimitReached() throws Exception { // given LoaderOptions loaderOptions = new LoaderOptions(); loaderOptions.setCodePointLimit(1); YAMLFactory yamlFactory = YAMLFactory.builder() .loaderOptions(loaderOptions) .build(); final String yaml = ResourceUtils.loadClassResource(getClass(), "specFiles/null-example.yaml"); // when OpenAPI deser = ObjectMapperFactory.createYaml(yamlFactory).readValue(yaml, OpenAPI.class); // then - Throw JacksonYAMLParseException } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/ModelSerializerTest.java ================================================ package io.swagger.v3.core.serialization; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.oas.models.Car; import io.swagger.v3.core.oas.models.Manufacturers; import io.swagger.v3.core.oas.models.ReadOnlyModel; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.ExternalDocumentation; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.DateSchema; import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.io.IOException; import java.math.BigDecimal; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class ModelSerializerTest { private final ObjectMapper m = Json.mapper(); @Test(description = "it should convert a model") public void convertModel() throws JsonProcessingException { final Schema pet = new Schema(); final Map props = new LinkedHashMap(); props.put("intValue", new IntegerSchema()); props.put("longValue", new IntegerSchema().format("int64")); props.put("dateValue", new DateSchema()); props.put("dateTimeValue", new DateTimeSchema()); pet.setProperties(props); pet.setRequired(Arrays.asList("intValue", "name")); final String json = "{\n" + " \"required\":[\n" + " \"intValue\"\n" + " ],\n" + " \"properties\":{\n" + " \"intValue\":{\n" + " \"type\":\"integer\",\n" + " \"format\":\"int32\"\n" + " },\n" + " \"longValue\":{\n" + " \"type\":\"integer\",\n" + " \"format\":\"int64\"\n" + " },\n" + " \"dateValue\":{\n" + " \"type\":\"string\",\n" + " \"format\":\"date\"\n" + " },\n" + " \"dateTimeValue\":{\n" + " \"type\":\"string\",\n" + " \"format\":\"date-time\"\n" + " }\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(pet, json); } @Test(description = "it should deserialize a model") public void deserializeModel() throws IOException { final String json = "{\n" + " \"required\":[\n" + " \"intValue\"\n" + " ],\n" + " \"type\":\"object\",\n" + " \"properties\":{\n" + " \"dateValue\":{\n" + " \"type\":\"string\",\n" + " \"format\":\"date\"\n" + " },\n" + " \"longValue\":{\n" + " \"type\":\"integer\",\n" + " \"format\":\"int64\"\n" + " },\n" + " \"dateTimeValue\":{\n" + " \"type\":\"string\",\n" + " \"format\":\"date-time\"\n" + " },\n" + " \"intValue\":{\n" + " \"type\":\"integer\",\n" + " \"format\":\"int32\"\n" + " },\n" + " \"byteArrayValue\":{\n" + " \"type\":\"string\",\n" + " \"format\":\"binary\"\n" + " }\n" + " }\n" + "}"; final Schema p = m.readValue(json, Schema.class); SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should serialize an array model") public void serializeArrayModel() throws IOException { final ArraySchema model = new ArraySchema(); model.setItems(new Schema().$ref("Pet")); assertEquals(m.writeValueAsString(model), "{\"type\":\"array\",\"items\":{\"$ref\":\"#/components/schemas/Pet\"}}"); } @Test(description = "it should deserialize an array model") public void deserializeArrayModel() throws IOException { final String json = "{\"type\":\"array\",\"items\":{\"$ref\":\"#/definitions/Pet\"}}"; final Schema p = m.readValue(json, Schema.class); assertTrue(p instanceof ArraySchema); assertEquals(m.writeValueAsString(p), json); } @Test(description = "it should not create an xml object for $ref") public void shouldNotCreateXmlObjectForRef() throws IOException { final Schema model = new Schema().$ref("Monster"); model.setDescription("oops"); model.setExternalDocs(new ExternalDocumentation() .description("external docs") .url("http://swagger.io")); assertEquals(Json.mapper().writeValueAsString(model), "{\"$ref\":\"#/components/schemas/Monster\"}"); } @Test(description = "it should make a field readOnly by annotation") public void makeFieldReadOnly() throws IOException { final Map schemas = ModelConverters.getInstance().read(Car.class); final String json = "{\n" + " \"Car\":{\n" + " \"type\":\"object\",\n" + " \"properties\":{\n" + " \"wheelCount\":{\n" + " \"type\":\"integer\",\n" + " \"format\":\"int32\",\n" + " \"readOnly\":true\n" + " }\n" + " }\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(schemas, json); } @Test(description = "it should serialize a model with a Set") public void serializeModelWithSet() throws IOException { final Map schemas = ModelConverters.getInstance().read(Manufacturers.class); final String json = "{\n" + " \"Manufacturers\":{\n" + " \"type\":\"object\",\n" + " \"properties\":{\n" + " \"countries\":{\n" + " \"type\":\"array\",\n" + " \"uniqueItems\":true,\n" + " \"items\":{\n" + " \"type\":\"string\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(schemas, json); } @Test(description = "it should deserialize a model with object example") public void deserializeModelWithObjectExample() throws IOException { final String json = "{\n" + " \"title\":\"Error\",\n" + " \"type\":\"object\",\n" + " \"properties\":{\n" + " \"code\":{\n" + " \"type\":\"integer\",\n" + " \"format\":\"int32\"\n" + " },\n" + " \"message\":{\n" + " \"type\":\"string\"\n" + " },\n" + " \"fields\":{\n" + " \"type\":\"string\"\n" + " }\n" + " },\n" + " \"example\":{\n" + " \"code\":1,\n" + " \"message\":\"hello\",\n" + " \"fields\":\"abc\"\n" + " }\n" + "}"; final Schema model = Json.mapper().readValue(json, Schema.class); assertEquals(Json.mapper().writeValueAsString(model.getExample()), "{\"code\":1,\"message\":\"hello\",\"fields\":\"abc\"}"); } @Test(description = "it should deserialize a model with read-only property") public void deserializeModelWithReadOnlyProperty() throws IOException { final String json = "{\n" + " \"properties\":{\n" + " \"id\":{\n" + " \"type\":\"integer\",\n" + " \"format\":\"int32\",\n" + " \"readOnly\":true\n" + " }\n" + " }\n" + "}"; final Schema model = Json.mapper().readValue(json, Schema.class); Schema property = (Schema) model.getProperties().get("id"); assertTrue(property.getReadOnly()); } @Test(description = "it should generate a JSON with read-only from pojo, #1161") public void readOnlyJsonGeneration() throws IOException { Map models = ModelConverters.getInstance().read(ReadOnlyModel.class); Schema model = models.get("ReadOnlyModel"); Schema id = (Schema) model.getProperties().get("id"); assertTrue(id.getReadOnly()); Schema readWriteId = (Schema) model.getProperties().get("readWriteId"); assertNull(readWriteId.getReadOnly()); } @Test(description = "it should generate an integer field with enum") public void integerEnumGeneration() throws IOException { final String json = "{\n" + " \"properties\":{\n" + " \"id\":{\n" + " \"description\":\"fun!\",\n" + " \"type\":\"integer\",\n" + " \"format\":\"int32\",\n" + " \"readOnly\":true,\n" + " \"enum\": [ 0, 1]\n" + " }\n" + " }\n" + "}"; final Schema model = Json.mapper().readValue(json, Schema.class); IntegerSchema p = (IntegerSchema) model.getProperties().get("id"); assertNotNull(p.getEnum()); assertEquals(p.getEnum().get(0), new Integer(0)); assertEquals(p.getEnum().get(1), new Integer(1)); } @Test(description = "it retains enums per ") public void testEnumParser() throws IOException { String json = "{\n" + " \"properties\": {\n" + " \"AdvStateType\": {\n" + " \"description\": \"Advertising State\",\n" + " \"enum\": [\n" + " \"off\",\n" + " \"on\"\n" + " ],\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + "}"; final Schema model = Json.mapper().readValue(json, Schema.class); StringSchema p = (StringSchema) model.getProperties().get("AdvStateType"); assertNotNull(p.getEnum()); assertEquals(p.getEnum().get(0), "off"); assertEquals(p.getEnum().get(1), "on"); } @Test public void testPrimitiveModel() throws Exception { String json = "{\n" + " \"type\": \"string\",\n" + " \"enum\": [\n" + " \"a\",\n" + " \"b\",\n" + " \"c\"\n" + " ]\n" + "}"; final Schema model = Json.mapper().readValue(json, Schema.class); assertNotNull(model.getEnum()); assertTrue(model.getEnum().size() == 3); } @Test public void testIssue1852() throws Exception { String json = "{\n" + " \"type\": \"integer\",\n" + " \"minimum\": 10,\n" + " \"maximum\": 20,\n" + " \"default\": 15\n" + "}"; final Schema model = Json.mapper().readValue(json, Schema.class); assertEquals(model.getMinimum().intValue(), 10); assertEquals(model.getMaximum().intValue(), 20); assertEquals(model.getDefault(), 15); } @Test public void testIssue2064Neg() throws Exception { String json = "{\n" + " \"type\": \"string\",\n" + " \"uniqueItems\": false\n" + "}"; final Schema model = Json.mapper().readValue(json, Schema.class); assertFalse(model.getUniqueItems()); } @Test public void testIssue2064() throws Exception { String json = "{\n" + " \"type\": \"string\",\n" + " \"uniqueItems\": true\n" + "}"; final Schema model = Json.mapper().readValue(json, Schema.class); assertTrue(model.getUniqueItems()); } @Test public void testIssue2064Ip() throws Exception { String json = "{\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"integer\",\n" + " \"format\": \"int32\",\n" + " \"multipleOf\": 3.0\n" + " }\n" + " }\n" + "}"; final Schema model = Json.mapper().readValue(json, Schema.class); IntegerSchema ip = (IntegerSchema) model.getProperties().get("id"); assertEquals(ip.getMultipleOf(), new BigDecimal("3.0")); } @Test public void testEnumWithNull() throws Exception { String yaml = "type: integer\n" + "description: some int values with null\n" + "format: int32\n" + "enum: \n" + "- 1\n" + "- 2\n" + "- null\n"; final Schema model = Yaml.mapper().readValue(yaml, Schema.class); assertEquals(model.getEnum(), Arrays.asList(1, 2, null)); SerializationMatchers.assertEqualsToYaml(model, yaml); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/Oas31ObjectFieldTest.java ================================================ package io.swagger.v3.core.serialization; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.oas.models.media.Schema; import org.testng.Assert; import org.testng.annotations.Test; import java.util.List; import java.util.Map; public class Oas31ObjectFieldTest { @Test(description = "Repro #4682: In OAS 3.1, raw Object property should not be rendered as an empty schema") public void rawObjectPropertyShouldBeObjectSchema() { Map schemas = ModelConverters.getInstance(true).readAll(PojoUsingObjectField.class); Schema pojo = schemas.get("PojoUsingObjectField"); Assert.assertNotNull(pojo, "PojoUsingObjectField schema should exist"); Schema myField = (Schema) pojo.getProperties().get("myField"); Assert.assertNotNull(myField, "myField schema should exist"); Assert.assertTrue(isObjectSchema(myField), "Expected raw Object property to be an object schema in OAS 3.1, but was: type=" + myField.getType() + ", types=" + myField.getTypes() + ", class=" + myField.getClass()); } @Test(description = "OAS 3.1: List items schema should be object") public void listOfObjectItemsShouldBeObjectSchema() { Map schemas = ModelConverters.getInstance(true).readAll(PojoUsingListOfObject.class); Schema pojo = schemas.get("PojoUsingListOfObject"); Assert.assertNotNull(pojo, "PojoUsingListOfObject schema should exist"); Schema itemsProp = (Schema) pojo.getProperties().get("items"); Assert.assertNotNull(itemsProp, "items property schema should exist"); Schema itemSchema = itemsProp.getItems(); Assert.assertNotNull(itemSchema, "List items schema should exist"); Assert.assertTrue(isObjectSchema(itemSchema), "Expected List items to be an object schema in OAS 3.1, but was: type=" + itemSchema.getType() + ", types=" + itemSchema.getTypes() + ", class=" + itemSchema.getClass()); } @Test(description = "OAS 3.1: Map additionalProperties schema should be object") public void mapOfObjectAdditionalPropertiesShouldBeObjectSchema() { Map schemas = ModelConverters.getInstance(true).readAll(PojoUsingMapStringToObject.class); Schema pojo = schemas.get("PojoUsingMapStringToObject"); Assert.assertNotNull(pojo, "PojoUsingMapStringToObject schema should exist"); Schema additionalProp = (Schema) pojo.getProperties().get("additional"); Assert.assertNotNull(additionalProp, "additional property schema should exist"); Schema valueSchema = (Schema) additionalProp.getAdditionalProperties(); Assert.assertNotNull(valueSchema, "Map additionalProperties (value schema) should exist"); Assert.assertTrue(isObjectSchema(valueSchema), "Expected Map additionalProperties to be an object schema in OAS 3.1, but was: type=" + valueSchema.getType() + ", types=" + valueSchema.getTypes() + ", class=" + valueSchema.getClass()); } /** * OAS 3.1 may represent types via Schema#getTypes() (JSON Schema style) rather than Schema#getType(). */ private static boolean isObjectSchema(Schema s) { if (s == null) return false; if ("object".equals(s.getType())) return true; return s.getTypes() != null && s.getTypes().contains("object"); } private static class PojoUsingObjectField { private Object myField; public Object getMyField() { return myField; } public void setMyField(Object myField) { this.myField = myField; } } private static class PojoUsingListOfObject { private List items; public List getItems() { return items; } public void setItems(List items) { this.items = items; } } private static class PojoUsingMapStringToObject { private Map additional; public Map getAdditional() { return additional; } public void setAdditional(Map additional) { this.additional = additional; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/OpenAPI3_1SerializationTest.java ================================================ package io.swagger.v3.core.serialization; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.util.DefaultIndenter; import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.dataformat.yaml.JacksonYAMLParseException; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.*; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.Discriminator; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityScheme; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import org.yaml.snakeyaml.LoaderOptions; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class OpenAPI3_1SerializationTest { private static final Logger LOGGER = LoggerFactory.getLogger(OpenAPI3_1SerializationTest.class); @Test public void testSerializePetstore() throws Exception { final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/petstore-3.1.yaml"); final OpenAPI swagger = Yaml31.mapper().readValue(jsonString, OpenAPI.class); assertNotNull(swagger); assertEquals(swagger.getInfo().getLicense().getIdentifier(), "test"); SerializationMatchers.assertEqualsToYaml31(swagger, "openapi: 3.1.0\n" + "info:\n" + " title: Swagger Petstore\n" + " license:\n" + " name: MIT\n" + " identifier: test\n" + " version: 1.0.0\n" + "servers:\n" + "- url: http://petstore.swagger.io/v1\n" + "paths:\n" + " /pets:\n" + " get:\n" + " tags:\n" + " - pets\n" + " summary: List all pets\n" + " operationId: listPets\n" + " parameters:\n" + " - name: limit\n" + " in: query\n" + " description: How many items to return at one time (max 100)\n" + " required: false\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " \"200\":\n" + " description: An paged array of pets\n" + " headers:\n" + " x-next:\n" + " description: A link to the next page of responses\n" + " schema:\n" + " type: string\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pets\"\n" + " default:\n" + " description: unexpected error\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Error\"\n" + " post:\n" + " tags:\n" + " - pets\n" + " summary: Create a pet\n" + " operationId: createPets\n" + " responses:\n" + " \"201\":\n" + " description: Null response\n" + " default:\n" + " description: unexpected error\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Error\"\n" + " /pets/{petId}:\n" + " get:\n" + " tags:\n" + " - pets\n" + " summary: Info for a specific pet\n" + " operationId: showPetById\n" + " parameters:\n" + " - name: petId\n" + " in: path\n" + " description: The id of the pet to retrieve\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " \"200\":\n" + " description: Expected response to a valid request\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pets\"\n" + " default:\n" + " description: unexpected error\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Error\"\n" + "components:\n" + " schemas:\n" + " Pet:\n" + " required:\n" + " - id\n" + " - name\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type:\n" + " - string\n" + " - integer\n" + " tag:\n" + " type: string\n" + " Pets:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " Error:\n" + " required:\n" + " - code\n" + " - message\n" + " properties:\n" + " code:\n" + " type: integer\n" + " format: int32\n" + " message:\n" + " type: string\n" + "webhooks:\n" + " newPet:\n" + " post:\n" + " requestBody:\n" + " description: Information about a new pet in the system\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " responses:\n" + " \"200\":\n" + " description: Return a 200 status to indicate that the data was received\n" + " successfully"); SerializationMatchers.assertEqualsToJson31(swagger, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"info\" : {\n" + " \"title\" : \"Swagger Petstore\",\n" + " \"license\" : {\n" + " \"name\" : \"MIT\",\n" + " \"identifier\" : \"test\"\n" + " },\n" + " \"version\" : \"1.0.0\"\n" + " },\n" + " \"servers\" : [ {\n" + " \"url\" : \"http://petstore.swagger.io/v1\"\n" + " } ],\n" + " \"paths\" : {\n" + " \"/pets\" : {\n" + " \"get\" : {\n" + " \"tags\" : [ \"pets\" ],\n" + " \"summary\" : \"List all pets\",\n" + " \"operationId\" : \"listPets\",\n" + " \"parameters\" : [ {\n" + " \"name\" : \"limit\",\n" + " \"in\" : \"query\",\n" + " \"description\" : \"How many items to return at one time (max 100)\",\n" + " \"required\" : false,\n" + " \"schema\" : {\n" + " \"type\" : \"integer\",\n" + " \"format\" : \"int32\"\n" + " }\n" + " } ],\n" + " \"responses\" : {\n" + " \"200\" : {\n" + " \"description\" : \"An paged array of pets\",\n" + " \"headers\" : {\n" + " \"x-next\" : {\n" + " \"description\" : \"A link to the next page of responses\",\n" + " \"schema\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"schema\" : {\n" + " \"$ref\" : \"#/components/schemas/Pets\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"default\" : {\n" + " \"description\" : \"unexpected error\",\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"schema\" : {\n" + " \"$ref\" : \"#/components/schemas/Error\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"post\" : {\n" + " \"tags\" : [ \"pets\" ],\n" + " \"summary\" : \"Create a pet\",\n" + " \"operationId\" : \"createPets\",\n" + " \"responses\" : {\n" + " \"201\" : {\n" + " \"description\" : \"Null response\"\n" + " },\n" + " \"default\" : {\n" + " \"description\" : \"unexpected error\",\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"schema\" : {\n" + " \"$ref\" : \"#/components/schemas/Error\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"/pets/{petId}\" : {\n" + " \"get\" : {\n" + " \"tags\" : [ \"pets\" ],\n" + " \"summary\" : \"Info for a specific pet\",\n" + " \"operationId\" : \"showPetById\",\n" + " \"parameters\" : [ {\n" + " \"name\" : \"petId\",\n" + " \"in\" : \"path\",\n" + " \"description\" : \"The id of the pet to retrieve\",\n" + " \"required\" : true,\n" + " \"schema\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " } ],\n" + " \"responses\" : {\n" + " \"200\" : {\n" + " \"description\" : \"Expected response to a valid request\",\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"schema\" : {\n" + " \"$ref\" : \"#/components/schemas/Pets\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"default\" : {\n" + " \"description\" : \"unexpected error\",\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"schema\" : {\n" + " \"$ref\" : \"#/components/schemas/Error\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"Pet\" : {\n" + " \"required\" : [ \"id\", \"name\" ],\n" + " \"properties\" : {\n" + " \"id\" : {\n" + " \"type\" : \"integer\",\n" + " \"format\" : \"int64\"\n" + " },\n" + " \"name\" : {\n" + " \"type\" : [\"string\", \"integer\"]\n" + " },\n" + " \"tag\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"Pets\" : {\n" + " \"type\" : \"array\",\n" + " \"items\" : {\n" + " \"$ref\" : \"#/components/schemas/Pet\"\n" + " }\n" + " },\n" + " \"Error\" : {\n" + " \"required\" : [ \"code\", \"message\" ],\n" + " \"properties\" : {\n" + " \"code\" : {\n" + " \"type\" : \"integer\",\n" + " \"format\" : \"int32\"\n" + " },\n" + " \"message\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"webhooks\" : {\n" + " \"newPet\" : {\n" + " \"post\" : {\n" + " \"requestBody\" : {\n" + " \"description\" : \"Information about a new pet in the system\",\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"schema\" : {\n" + " \"$ref\" : \"#/components/schemas/Pet\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"responses\" : {\n" + " \"200\" : {\n" + " \"description\" : \"Return a 200 status to indicate that the data was received successfully\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testJSONSerializePetstoreWithCustomFactory() throws Exception { //given final String jsonString = ResourceUtils.loadClassResource(getClass(), "specFiles/3.1.0/petstore-3.1.json"); JsonFactory jsonFactory = new JsonFactory(); //when final OpenAPI swagger = ObjectMapperFactory.createJson31(jsonFactory).readValue(jsonString, OpenAPI.class); // then assertNotNull(swagger); SerializationMatchers.assertEqualsToJson31(swagger, jsonString); } @Test public void testInfoSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .info(new Info() .title("Title test") .description("This is a description for test") .summary("Test Summary") .version("1.0.0") .termsOfService("https://test.term.of.services") .contact(new Contact() .name("Test Contact") .url("https://test.contact.url") .email("test@email.com")) .license(new License() .name("test license") .url("https://test.license.com") .identifier("swagger"))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "info:\n" + " title: Title test\n" + " description: This is a description for test\n" + " summary: Test Summary\n" + " termsOfService: https://test.term.of.services\n" + " contact:\n" + " name: Test Contact\n" + " url: https://test.contact.url\n" + " email: test@email.com\n" + " license:\n" + " name: test license\n" + " url: https://test.license.com\n" + " identifier: swagger\n" + " version: 1.0.0"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"info\" : {\n" + " \"title\" : \"Title test\",\n" + " \"description\" : \"This is a description for test\",\n" + " \"summary\" : \"Test Summary\",\n" + " \"termsOfService\" : \"https://test.term.of.services\",\n" + " \"contact\" : {\n" + " \"name\" : \"Test Contact\",\n" + " \"url\" : \"https://test.contact.url\",\n" + " \"email\" : \"test@email.com\"\n" + " },\n" + " \"license\" : {\n" + " \"name\" : \"test license\",\n" + " \"url\" : \"https://test.license.com\",\n" + " \"identifier\" : \"swagger\"\n" + " },\n" + " \"version\" : \"1.0.0\"\n" + " }\n" + "}"); openAPI.setOpenapi("3.0.3"); SerializationMatchers.assertEqualsToYaml(openAPI, "openapi: 3.0.3\n" + "info:\n" + " title: Title test\n" + " description: This is a description for test\n" + " termsOfService: https://test.term.of.services\n" + " contact:\n" + " name: Test Contact\n" + " url: https://test.contact.url\n" + " email: test@email.com\n" + " license:\n" + " name: test license\n" + " url: https://test.license.com\n" + " version: 1.0.0"); SerializationMatchers.assertEqualsToJson(openAPI, "{\n" + " \"openapi\" : \"3.0.3\",\n" + " \"info\" : {\n" + " \"title\" : \"Title test\",\n" + " \"description\" : \"This is a description for test\",\n" + " \"termsOfService\" : \"https://test.term.of.services\",\n" + " \"contact\" : {\n" + " \"name\" : \"Test Contact\",\n" + " \"url\" : \"https://test.contact.url\",\n" + " \"email\" : \"test@email.com\"\n" + " },\n" + " \"license\" : {\n" + " \"name\" : \"test license\",\n" + " \"url\" : \"https://test.license.com\"\n" + " },\n" + " \"version\" : \"1.0.0\"\n" + " }\n" + "}"); } @Test public void testWebHooksSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .addWebhooks("hook", new PathItem() .description("test path hook") .get(new Operation() .operationId("testHookOperation") .responses(new ApiResponses() .addApiResponse("200", new ApiResponse().description("test response description"))))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "webhooks:\n" + " hook:\n" + " description: test path hook\n" + " get:\n" + " operationId: testHookOperation\n" + " responses:\n" + " \"200\":\n" + " description: test response description"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"webhooks\" : {\n" + " \"hook\" : {\n" + " \"description\" : \"test path hook\",\n" + " \"get\" : {\n" + " \"operationId\" : \"testHookOperation\",\n" + " \"responses\" : {\n" + " \"200\" : {\n" + " \"description\" : \"test response description\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"); openAPI.setOpenapi("3.0.3"); SerializationMatchers.assertEqualsToYaml(openAPI, "openapi: 3.0.3"); SerializationMatchers.assertEqualsToJson(openAPI, "{\n" + " \"openapi\" : \"3.0.3\"\n}"); } @Test public void testComponentPathItemsSerialization() { Schema schema = new StringSchema(); schema.addType(schema.getType()); OpenAPI openAPI = new OpenAPI().openapi("3.1.0").components(new Components() .addSchemas("stringTest", schema) .addPathItem("/pathTest", new PathItem() .description("test path item") .get(new Operation() .operationId("testPathItem") .responses(new ApiResponses() .addApiResponse("200", new ApiResponse().description("response description"))))) .addResponses("201", new ApiResponse() .description("api response description")) .addParameters("param", new Parameter() .in("query") .description("parameter description") .schema(schema)) .addExamples("example", new Example() .summary("example summary") .value("This is an example/") .description("example description")) .addRequestBodies("body", new RequestBody() .content(new Content() .addMediaType("application/json", new MediaType() .schema(new ObjectSchema())))) .addHeaders("test-head", new Header() .description("test header description")) .addSecuritySchemes("basic", new SecurityScheme() .in(SecurityScheme.In.HEADER) .scheme("http") .description("ref security description")) .addLinks("Link", new Link() .operationRef("#/paths/~12.0~1repositories~1{username}/get")) .addCallbacks("TestCallback", new Callback().addPathItem("{$request.query.queryUrl}", new PathItem() .description("test path item") .post(new Operation() .operationId("testPathItem"))))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "components:\n" + " schemas:\n" + " stringTest:\n" + " type: string\n" + " responses:\n" + " \"201\":\n" + " description: api response description\n" + " parameters:\n" + " param:\n" + " in: query\n" + " description: parameter description\n" + " schema:\n" + " type: string\n" + " examples:\n" + " example:\n" + " summary: example summary\n" + " description: example description\n" + " value: This is an example/\n" + " requestBodies:\n" + " body:\n" + " content:\n" + " application/json:\n" + " schema: \n" + " type: object\n" + " headers:\n" + " test-head:\n" + " description: test header description\n" + " securitySchemes:\n" + " basic:\n" + " description: ref security description\n" + " in: header\n" + " scheme: http\n" + " links:\n" + " Link:\n" + " operationRef: \"#/paths/~12.0~1repositories~1{username}/get\"\n" + " callbacks:\n" + " TestCallback:\n" + " '{$request.query.queryUrl}':\n" + " description: test path item\n" + " post:\n" + " operationId: testPathItem\n" + " pathItems:\n" + " /pathTest:\n" + " description: test path item\n" + " get:\n" + " operationId: testPathItem\n" + " responses:\n" + " \"200\":\n" + " description: response description"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"stringTest\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " },\n" + " \"responses\" : {\n" + " \"201\" : {\n" + " \"description\" : \"api response description\"\n" + " }\n" + " },\n" + " \"parameters\" : {\n" + " \"param\" : {\n" + " \"in\" : \"query\",\n" + " \"description\" : \"parameter description\",\n" + " \"schema\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"examples\" : {\n" + " \"example\" : {\n" + " \"summary\" : \"example summary\",\n" + " \"description\" : \"example description\",\n" + " \"value\" : \"This is an example/\"\n" + " }\n" + " },\n" + " \"requestBodies\" : {\n" + " \"body\" : {\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"schema\" : {\n" + " \"type\" : \"object\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"headers\" : {\n" + " \"test-head\" : {\n" + " \"description\" : \"test header description\"\n" + " }\n" + " },\n" + " \"securitySchemes\" : {\n" + " \"basic\" : {\n" + " \"description\" : \"ref security description\",\n" + " \"in\" : \"header\",\n" + " \"scheme\" : \"http\"\n" + " }\n" + " },\n" + " \"links\" : {\n" + " \"Link\" : {\n" + " \"operationRef\" : \"#/paths/~12.0~1repositories~1{username}/get\"\n" + " }\n" + " },\n" + " \"callbacks\" : {\n" + " \"TestCallback\" : {\n" + " \"{$request.query.queryUrl}\" : {\n" + " \"description\" : \"test path item\",\n" + " \"post\" : {\n" + " \"operationId\" : \"testPathItem\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"pathItems\" : {\n" + " \"/pathTest\" : {\n" + " \"description\" : \"test path item\",\n" + " \"get\" : {\n" + " \"operationId\" : \"testPathItem\",\n" + " \"responses\" : {\n" + " \"200\" : {\n" + " \"description\" : \"response description\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"); openAPI.openapi("3.0.3"); SerializationMatchers.assertEqualsToYaml(openAPI, "openapi: 3.0.3\n" + "components:\n" + " schemas:\n" + " stringTest:\n" + " type: string\n" + " responses:\n" + " \"201\":\n" + " description: api response description\n" + " parameters:\n" + " param:\n" + " in: query\n" + " description: parameter description\n" + " schema:\n" + " type: string\n" + " examples:\n" + " example:\n" + " summary: example summary\n" + " description: example description\n" + " value: This is an example/\n" + " requestBodies:\n" + " body:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: object\n" + " headers:\n" + " test-head:\n" + " description: test header description\n" + " securitySchemes:\n" + " basic:\n" + " description: ref security description\n" + " in: header\n" + " scheme: http\n" + " links:\n" + " Link:\n" + " operationRef: \"#/paths/~12.0~1repositories~1{username}/get\"\n" + " callbacks:\n" + " TestCallback:\n" + " '{$request.query.queryUrl}':\n" + " description: test path item\n" + " post:\n" + " operationId: testPathItem"); SerializationMatchers.assertEqualsToJson(openAPI, "{\n" + " \"openapi\" : \"3.0.3\",\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"stringTest\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " },\n" + " \"responses\" : {\n" + " \"201\" : {\n" + " \"description\" : \"api response description\"\n" + " }\n" + " },\n" + " \"parameters\" : {\n" + " \"param\" : {\n" + " \"in\" : \"query\",\n" + " \"description\" : \"parameter description\",\n" + " \"schema\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"examples\" : {\n" + " \"example\" : {\n" + " \"summary\" : \"example summary\",\n" + " \"description\" : \"example description\",\n" + " \"value\" : \"This is an example/\"\n" + " }\n" + " },\n" + " \"requestBodies\" : {\n" + " \"body\" : {\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"schema\" : {\n" + " \"type\" : \"object\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"headers\" : {\n" + " \"test-head\" : {\n" + " \"description\" : \"test header description\"\n" + " }\n" + " },\n" + " \"securitySchemes\" : {\n" + " \"basic\" : {\n" + " \"description\" : \"ref security description\",\n" + " \"in\" : \"header\",\n" + " \"scheme\" : \"http\"\n" + " }\n" + " },\n" + " \"links\" : {\n" + " \"Link\" : {\n" + " \"operationRef\" : \"#/paths/~12.0~1repositories~1{username}/get\"\n" + " }\n" + " },\n" + " \"callbacks\" : {\n" + " \"TestCallback\" : {\n" + " \"{$request.query.queryUrl}\" : {\n" + " \"description\" : \"test path item\",\n" + " \"post\" : {\n" + " \"operationId\" : \"testPathItem\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testDiscriminatorSerialization() { Schema propertySchema1 = new StringSchema(); propertySchema1.addType(propertySchema1.getType()); Schema propertySchema2 = new StringSchema(); propertySchema2.addType(propertySchema2.getType()); Discriminator discriminator = new Discriminator().propertyName("type"); discriminator.addExtension("x-otherName", "discriminationType"); Schema schema = new ObjectSchema() .addProperties("name", propertySchema1) .addProperties("type", propertySchema1) .discriminator(discriminator); schema.addType(schema.getType()); OpenAPI openAPI = new OpenAPI().openapi("3.1.0").components(new Components() .addSchemas("pet", schema)); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "components:\n" + " schemas:\n" + " pet:\n" + " properties:\n" + " name:\n" + " type: string\n" + " type:\n" + " type: string\n" + " discriminator:\n" + " propertyName: type\n" + " x-otherName: discriminationType\n" + " type: object"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"pet\" : {\n" + " \"properties\" : {\n" + " \"name\" : {\n" + " \"type\" : \"string\"\n" + " },\n" + " \"type\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " },\n" + " \"discriminator\" : {\n" + " \"propertyName\" : \"type\",\n" + " \"x-otherName\" : \"discriminationType\"\n" + " },\n" + " \"type\" : \"object\"\n" + " }\n" + " }\n" + " }\n" + "}"); openAPI.openapi("3.0.3"); SerializationMatchers.assertEqualsToYaml(openAPI, "openapi: 3.0.3\n" + "components:\n" + " schemas:\n" + " pet:\n" + " properties:\n" + " name:\n" + " type: string\n" + " type:\n" + " type: string\n" + " discriminator:\n" + " propertyName: type\n" + " type: object"); SerializationMatchers.assertEqualsToJson(openAPI, "{\n" + " \"openapi\" : \"3.0.3\",\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"pet\" : {\n" + " \"properties\" : {\n" + " \"name\" : {\n" + " \"type\" : \"string\"\n" + " },\n" + " \"type\" : {\n" + " \"type\" : \"string\"\n" + " }\n" + " },\n" + " \"discriminator\" : {\n" + " \"propertyName\" : \"type\"\n" + " },\n" + " \"type\" : \"object\"\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testPathItemsRefSerialization() { OpenAPI openAPI = new OpenAPI().openapi("3.1.0") .path("/pathTest", new PathItem() .$ref("#/components/pathItems/pathTest") .description("This is a ref path item") .summary("ref path item") ) .components(new Components() .addPathItem("pathTest", new PathItem() .description("test path item") .get(new Operation() .operationId("testPathItem") .responses(new ApiResponses() .addApiResponse("200", new ApiResponse().description("response description")))))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "paths:\n" + " /pathTest:\n" + " $ref: \"#/components/pathItems/pathTest\"\n" + " description: This is a ref path item\n" + " summary: ref path item\n" + "components:\n" + " pathItems:\n" + " pathTest:\n" + " description: test path item\n" + " get:\n" + " operationId: testPathItem\n" + " responses:\n" + " \"200\":\n" + " description: response description"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"paths\" : {\n" + " \"/pathTest\" : {\n" + " \"summary\" : \"ref path item\",\n" + " \"description\" : \"This is a ref path item\",\n" + " \"$ref\" : \"#/components/pathItems/pathTest\"\n" + " }\n" + " },\n" + " \"components\" : {\n" + " \"pathItems\" : {\n" + " \"pathTest\" : {\n" + " \"description\" : \"test path item\",\n" + " \"get\" : {\n" + " \"operationId\" : \"testPathItem\",\n" + " \"responses\" : {\n" + " \"200\" : {\n" + " \"description\" : \"response description\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testResponseRefSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .path("/test", new PathItem() .description("test path item") .get(new Operation() .operationId("testPathItem") .responses(new ApiResponses() .addApiResponse("200" , new ApiResponse() .description("point to a $ref response") .$ref("#/components/responses/okResponse"))))) .components(new Components() .addResponses("okResponse", new ApiResponse().description("everything is good"))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " description: test path item\n" + " get:\n" + " operationId: testPathItem\n" + " responses:\n" + " \"200\":\n" + " description: point to a $ref response\n" + " $ref: \"#/components/responses/okResponse\"\n" + "components:\n" + " responses:\n" + " okResponse:\n" + " description: everything is good"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"paths\" : {\n" + " \"/test\" : {\n" + " \"description\" : \"test path item\",\n" + " \"get\" : {\n" + " \"operationId\" : \"testPathItem\",\n" + " \"responses\" : {\n" + " \"200\" : {\n" + " \"description\" : \"point to a $ref response\",\n" + " \"$ref\" : \"#/components/responses/okResponse\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"components\" : {\n" + " \"responses\" : {\n" + " \"okResponse\" : {\n" + " \"description\" : \"everything is good\"\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testParameterRefSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .components(new Components() .addParameters("testParameter", new Parameter() .in("query"))) .path("/test", new PathItem() .description("test path item") .get(new Operation() .operationId("testPathItem") .addParametersItem(new Parameter() .$ref("#/components/parameters/testParameter") .description("test parameter")))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " description: test path item\n" + " get:\n" + " operationId: testPathItem\n" + " parameters:\n" + " - description: test parameter\n" + " $ref: \"#/components/parameters/testParameter\"\n" + "components:\n" + " parameters:\n" + " testParameter:\n" + " in: query"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"paths\" : {\n" + " \"/test\" : {\n" + " \"description\" : \"test path item\",\n" + " \"get\" : {\n" + " \"operationId\" : \"testPathItem\",\n" + " \"parameters\" : [ {\n" + " \"description\" : \"test parameter\",\n" + " \"$ref\" : \"#/components/parameters/testParameter\"\n" + " } ]\n" + " }\n" + " }\n" + " },\n" + " \"components\" : {\n" + " \"parameters\" : {\n" + " \"testParameter\" : {\n" + " \"in\" : \"query\"\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testExampleRefSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .components(new Components() .addExamples("testExample", new Example() .value("Example on test") .description("this is a example desc") .summary("this is a summary test")) .addSchemas("schema", new Schema().example(new Example() .$ref("#/components/examples/testExample") .description("ref description") .summary("ref summary")))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "components:\n" + " schemas:\n" + " schema:\n" + " example:\n" + " summary: ref summary\n" + " description: ref description\n" + " $ref: \"#/components/examples/testExample\"\n" + " examples:\n" + " testExample:\n" + " summary: this is a summary test\n" + " description: this is a example desc\n" + " value: Example on test"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"schema\" : {\n" + " \"example\" : {\n" + " \"summary\" : \"ref summary\",\n" + " \"description\" : \"ref description\",\n" + " \"$ref\" : \"#/components/examples/testExample\"\n" + " }\n" + " }\n" + " },\n" + " \"examples\" : {\n" + " \"testExample\" : {\n" + " \"summary\" : \"this is a summary test\",\n" + " \"description\" : \"this is a example desc\",\n" + " \"value\" : \"Example on test\"\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testRequestBodyRefSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .path("/test", new PathItem() .description("test path item") .post(new Operation() .operationId("testPathItem") .requestBody(new RequestBody() .$ref("#/components/requestBodies/body") .description("ref request body")))) .components(new Components() .addRequestBodies("body", new RequestBody() .content(new Content() .addMediaType("application/json", new MediaType() .schema(new ObjectSchema()))))) ; SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " description: test path item\n" + " post:\n" + " operationId: testPathItem\n" + " requestBody:\n" + " description: ref request body\n" + " $ref: \"#/components/requestBodies/body\"\n" + "components:\n" + " requestBodies:\n" + " body:\n" + " content:\n" + " application/json:\n" + " schema: \n" + " type: object"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"paths\" : {\n" + " \"/test\" : {\n" + " \"description\" : \"test path item\",\n" + " \"post\" : {\n" + " \"operationId\" : \"testPathItem\",\n" + " \"requestBody\" : {\n" + " \"description\" : \"ref request body\",\n" + " \"$ref\" : \"#/components/requestBodies/body\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"components\" : {\n" + " \"requestBodies\" : {\n" + " \"body\" : {\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"schema\" : {\n" + " \"type\" : \"object\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testHeaderRefSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .path("/test", new PathItem() .description("test path item") .post(new Operation() .operationId("testPathItem") .responses(new ApiResponses() .addApiResponse("default", new ApiResponse() .description("default response") .addHeaderObject("header", new Header() .$ref("#/components/responses/okResponse") .description("ref header description")))) )) .components(new Components() .addHeaders("test-head", new Header() .description("test header description"))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " description: test path item\n" + " post:\n" + " operationId: testPathItem\n" + " responses:\n" + " default:\n" + " description: default response\n" + " headers:\n" + " header:\n" + " description: ref header description\n" + " $ref: \"#/components/responses/okResponse\"\n" + "components:\n" + " headers:\n" + " test-head:\n" + " description: test header description"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"paths\" : {\n" + " \"/test\" : {\n" + " \"description\" : \"test path item\",\n" + " \"post\" : {\n" + " \"operationId\" : \"testPathItem\",\n" + " \"responses\" : {\n" + " \"default\" : {\n" + " \"description\" : \"default response\",\n" + " \"headers\" : {\n" + " \"header\" : {\n" + " \"description\" : \"ref header description\",\n" + " \"$ref\" : \"#/components/responses/okResponse\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"components\" : {\n" + " \"headers\" : {\n" + " \"test-head\" : {\n" + " \"description\" : \"test header description\"\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testSecuritySchemeRefSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .components(new Components().addSecuritySchemes("basic", new SecurityScheme() .$ref("https://external.site.com/#components/securitySchemes/basic") .description("ref security description"))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "components:\n" + " securitySchemes:\n" + " basic:\n" + " description: ref security description\n" + " $ref: https://external.site.com/#components/securitySchemes/basic"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"components\" : {\n" + " \"securitySchemes\" : {\n" + " \"basic\" : {\n" + " \"description\" : \"ref security description\",\n" + " \"$ref\" : \"https://external.site.com/#components/securitySchemes/basic\"\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testLinkRefSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .path("/test", new PathItem() .description("test path item") .post(new Operation() .operationId("testPathItem") .responses(new ApiResponses() .addApiResponse("default", new ApiResponse() .description("default response") .addLink("link", new Link() .$ref("#/components/links/Link") .description("ref link description")))))) .components(new Components().addLinks("Link", new Link() .operationRef("#/paths/~12.0~1repositories~1{username}/get"))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " description: test path item\n" + " post:\n" + " operationId: testPathItem\n" + " responses:\n" + " default:\n" + " description: default response\n" + " links:\n" + " link:\n" + " description: ref link description\n" + " $ref: \"#/components/links/Link\"\n" + "components:\n" + " links:\n" + " Link:\n" + " operationRef: \"#/paths/~12.0~1repositories~1{username}/get\""); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"paths\" : {\n" + " \"/test\" : {\n" + " \"description\" : \"test path item\",\n" + " \"post\" : {\n" + " \"operationId\" : \"testPathItem\",\n" + " \"responses\" : {\n" + " \"default\" : {\n" + " \"description\" : \"default response\",\n" + " \"links\" : {\n" + " \"link\" : {\n" + " \"description\" : \"ref link description\",\n" + " \"$ref\" : \"#/components/links/Link\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"components\" : {\n" + " \"links\" : {\n" + " \"Link\" : {\n" + " \"operationRef\" : \"#/paths/~12.0~1repositories~1{username}/get\"\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testCallRefSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .path("/test", new PathItem() .description("test path item") .post(new Operation() .operationId("testPathItem") .addCallback("callbackSample", new Callback() .$ref("#/components/callbacks/TestCallback")))) .components(new Components().addCallbacks("TestCallback", new Callback().addPathItem("{$request.query.queryUrl}", new PathItem() .description("test path item") .post(new Operation() .operationId("testPathItem"))))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " description: test path item\n" + " post:\n" + " operationId: testPathItem\n" + " callbacks:\n" + " callbackSample:\n" + " $ref: \"#/components/callbacks/TestCallback\"\n" + "components:\n" + " callbacks:\n" + " TestCallback:\n" + " '{$request.query.queryUrl}':\n" + " description: test path item\n" + " post:\n" + " operationId: testPathItem"); SerializationMatchers.assertEqualsToJson31(openAPI, "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"paths\" : {\n" + " \"/test\" : {\n" + " \"description\" : \"test path item\",\n" + " \"post\" : {\n" + " \"operationId\" : \"testPathItem\",\n" + " \"callbacks\" : {\n" + " \"callbackSample\" : {\n" + " \"$ref\" : \"#/components/callbacks/TestCallback\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"components\" : {\n" + " \"callbacks\" : {\n" + " \"TestCallback\" : {\n" + " \"{$request.query.queryUrl}\" : {\n" + " \"description\" : \"test path item\",\n" + " \"post\" : {\n" + " \"operationId\" : \"testPathItem\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"); } @Test public void testBooleanSchemaSerialization() { OpenAPI openAPI = new OpenAPI() .openapi("3.1.0") .components(new Components().addSchemas("test", new Schema().booleanSchemaValue(true))); LOGGER.debug("--------- root ----------"); Json31.prettyPrint(openAPI); assertEquals(Json31.pretty(openAPI), withJacksonSystemLineSeparator("{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"test\" : true\n" + " }\n" + " }\n" + "}")); LOGGER.debug("--------- schema ----------"); Json31.prettyPrint(openAPI.getComponents().getSchemas().get("test")); assertEquals(Json31.pretty(openAPI.getComponents().getSchemas().get("test")), "true"); LOGGER.debug("--------- root YAML----------"); Yaml31.prettyPrint(openAPI); assertEquals(Yaml31.pretty(openAPI), "openapi: 3.1.0\n" + "components:\n" + " schemas:\n" + " test: true\n"); LOGGER.debug("--------- schema YAML ----------"); Yaml31.prettyPrint(openAPI.getComponents().getSchemas().get("test")); assertEquals(Yaml31.pretty(openAPI.getComponents().getSchemas().get("test")), "true\n"); LOGGER.debug("--------- root 3.0 ----------"); Json.prettyPrint(openAPI); assertEquals(Json.pretty(openAPI), withJacksonSystemLineSeparator("{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"test\" : { }\n" + " }\n" + " }\n" + "}")); LOGGER.debug("--------- schema 3.0 ----------"); Json.prettyPrint(openAPI.getComponents().getSchemas().get("test")); assertEquals(Json.pretty(openAPI.getComponents().getSchemas().get("test")), "{ }"); LOGGER.debug("--------- root YAML 3.0 ----------"); Yaml.prettyPrint(openAPI); assertEquals(Yaml.pretty(openAPI), "openapi: 3.1.0\n" + "components:\n" + " schemas:\n" + " test: {}\n"); LOGGER.debug("--------- schema YAML 3.0 ----------"); Yaml.prettyPrint(openAPI.getComponents().getSchemas().get("test")); assertEquals(Yaml.pretty(openAPI.getComponents().getSchemas().get("test")), "{}\n"); } @Test public void testBooleanAdditionalPropertiesSerialization() throws Exception{ String expectedJson = "{\n" + " \"openapi\" : \"3.1.0\",\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"test\" : {\n" + " \"type\" : \"object\",\n" + " \"additionalProperties\" : true\n" + " }\n" + " }\n" + " }\n" + "}"; String expectedYaml = "openapi: 3.1.0\n" + "components:\n" + " schemas:\n" + " test:\n" + " type: object\n" + " additionalProperties: true\n"; OpenAPI openAPI = Json31.mapper().readValue(expectedJson, OpenAPI.class); String ser = Json31.pretty(openAPI); assertEquals(ser, withJacksonSystemLineSeparator(expectedJson)); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); openAPI = Json.mapper().readValue(expectedJson, OpenAPI.class); ser = Json.pretty(openAPI); assertEquals(ser, withJacksonSystemLineSeparator(expectedJson)); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); openAPI = Yaml31.mapper().readValue(expectedYaml, OpenAPI.class); ser = Yaml31.pretty(openAPI); assertEquals(ser, expectedYaml); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); openAPI = Yaml.mapper().readValue(expectedYaml, OpenAPI.class); ser = Yaml.pretty(openAPI); assertEquals(ser, expectedYaml); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); expectedJson = "{\n" + " \"openapi\" : \"3.0.0\",\n" + " \"components\" : {\n" + " \"schemas\" : {\n" + " \"test\" : {\n" + " \"type\" : \"object\",\n" + " \"additionalProperties\" : true\n" + " }\n" + " }\n" + " }\n" + "}"; expectedYaml = "openapi: 3.0.0\n" + "components:\n" + " schemas:\n" + " test:\n" + " type: object\n" + " additionalProperties: true\n"; openAPI = Json31.mapper().readValue(expectedJson, OpenAPI.class); ser = Json31.pretty(openAPI); assertEquals(ser, withJacksonSystemLineSeparator(expectedJson)); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); openAPI = Json.mapper().readValue(expectedJson, OpenAPI.class); ser = Json.pretty(openAPI); assertEquals(ser, withJacksonSystemLineSeparator(expectedJson)); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); openAPI = Yaml31.mapper().readValue(expectedYaml, OpenAPI.class); ser = Yaml31.pretty(openAPI); assertEquals(ser, expectedYaml); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); openAPI = Yaml.mapper().readValue(expectedYaml, OpenAPI.class); ser = Yaml.pretty(openAPI); assertEquals(ser, expectedYaml); assertTrue(Boolean.TRUE.equals(openAPI.getComponents().getSchemas().get("test").getAdditionalProperties())); } @Test(expectedExceptions = JacksonYAMLParseException.class) public void testSerializeYAML31WithCustomFactoryAndCodePointLimitReached() throws Exception { // given LoaderOptions loaderOptions = new LoaderOptions(); loaderOptions.setCodePointLimit(1); YAMLFactory yamlFactory = YAMLFactory.builder() .loaderOptions(loaderOptions) .build(); final String yaml = ResourceUtils.loadClassResource(getClass(), "specFiles/petstore-3.0.yaml"); // when OpenAPI deser = ObjectMapperFactory.createYaml31(yamlFactory).readValue(yaml, OpenAPI.class); // then - Throw JacksonYAMLParseException } private static String withJacksonSystemLineSeparator(String s) { return s.replace("\n", DefaultIndenter.SYS_LF); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/ParameterSerializationTest.java ================================================ package io.swagger.v3.core.serialization; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.NumberSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.HeaderParameter; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.PathParameter; import io.swagger.v3.oas.models.parameters.QueryParameter; import io.swagger.v3.oas.models.parameters.RequestBody; import org.testng.annotations.Test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; public class ParameterSerializationTest { private final ObjectMapper m = Json.mapper(); @Test(description = "it should serialize a QueryParameter") public void serializeQueryParameter() { final Parameter p = new QueryParameter() .schema(new StringSchema()); final String json = "{\"in\":\"query\",\"schema\":{\"type\":\"string\"}}"; SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should serialize a QueryParameter with array") public void serializeArrayQueryParameter() { final Parameter p = new QueryParameter() .schema(new ArraySchema() .items(new StringSchema())); final String json = "{" + " \"in\":\"query\"," + " \"schema\":{" + " \"type\":\"array\"," + " \"items\":{" + " \"type\":\"string\"" + " }}" + "}"; SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should serialize a PathParameter") public void serializePathParameter() { final Parameter p = new PathParameter().schema(new StringSchema()); final String json = "{\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"string\"}}"; SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should serialize a PathParameter with string array") public void serializeStringArrayPathParameter() { Parameter p = new PathParameter() .schema(new ArraySchema() .items(new StringSchema())); final String json = "{\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}}"; SerializationMatchers.assertEqualsToJson(p, json); final String yaml = "---\n" + "in: \"path\"\n" + "required: true\n" + "schema:\n" + " type: \"array\"\n" + " items:\n" + " type: \"string\""; SerializationMatchers.assertEqualsToYaml(p, yaml); } @Test(description = "it should serialize a PathParameter with integer array") public void serializeIntegerArrayPathParameter() { final Parameter p = new PathParameter() .schema(new ArraySchema().items(new IntegerSchema())); final String json = "{\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"array\",\"items\":{\"type\":\"integer\",\"format\":\"int32\"}}}\n"; SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should it should serialize a HeaderParameter") public void serializeHeaderParameter() { final Parameter p = new HeaderParameter() .schema(new StringSchema()); final String json = "{\"in\":\"header\",\"schema\":{\"type\":\"string\"}}"; SerializationMatchers.assertEqualsToJson(p, json); final String yaml = "---\n" + "in: \"header\"\n" + "schema:\n" + " type: \"string\""; SerializationMatchers.assertEqualsToYaml(p, yaml); } @Test(description = "it should serialize a string array HeaderParameter") public void serializeStringArrayHeaderParameter() { final Parameter p = new HeaderParameter() .schema(new ArraySchema() .items(new StringSchema())); final String json = "{\"in\":\"header\",\"schema\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}}"; SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should serialize a BodyParameter") public void serializeBodyParameter() { final Schema model = new Schema() .title("Cat") .addProperties("name", new StringSchema()); final RequestBody p = new RequestBody() .content(new Content().addMediaType("*/*", new MediaType().schema(model))); final String json = "{\"content\":{\"*/*\":{\"schema\":{\"title\":\"Cat\",\"properties\":{\"name\":{\"type\":\"string\"}}}}}}"; SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should serialize a BodyParameter to yaml") public void serializeBodyParameterToYaml() { final Schema model = new Schema() .title("Cat") .addProperties("name", new StringSchema()); final RequestBody p = new RequestBody() .content(new Content().addMediaType("*/*", new MediaType().schema(model))); final String yaml = "---\n" + "content:\n" + " '*/*':\n" + " schema:\n" + " title: Cat\n" + " properties:\n" + " name:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(p, yaml); } @Test(description = "it should serialize a ref BodyParameter") public void serializeRefBodyParameter() { final Schema model = new Schema().$ref("#/definitions/Cat"); final RequestBody p = new RequestBody() .content(new Content().addMediaType("*/*", new MediaType().schema(model))); final String json = "{\"content\":{\"*/*\":{\"schema\":{\"$ref\":\"#/definitions/Cat\"}}}}"; SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should serialize an array BodyParameter") public void serializeArrayBodyParameter() { final Schema model = new ArraySchema().items(new Schema().$ref("#/definitions/Cat")); final RequestBody p = new RequestBody() .content(new Content().addMediaType("*/*", new MediaType().schema(model))); final String json = "{\"content\":{\"*/*\":{\"schema\":{\"type\":\"array\",\"items\":{\"$ref\":\"#/definitions/Cat\"}}}}}"; SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "it should serialize a path parameter with enum") public void serializeEnumPathParameter() { List values = new ArrayList<>(); values.add("a"); values.add("b"); values.add("c"); Parameter p = new PathParameter() .schema(new StringSchema()._enum(values)); final String json = "{" + " \"in\":\"path\"," + " \"required\":true," + " \"schema\":{" + " \"type\":\"string\"," + " \"enum\":[\"a\",\"b\",\"c\"]" + " }" + "}"; SerializationMatchers.assertEqualsToJson(p, json); } @Test(description = "should serialize correctly typed numeric enums") public void testIssue1765() throws Exception { String yaml = "openapi: '3.0.1'\n" + "paths:\n" + " /test:\n" + " get:\n" + " parameters:\n" + " - name: \"days\"\n" + " in: \"path\"\n" + " required: true\n" + " schema:\n" + " type: \"integer\"\n" + " format: \"int32\"\n" + " enum:\n" + " - 1\n" + " - 2\n" + " - 3\n" + " - 4\n" + " - 5\n" + " responses:\n" + " default:\n" + " description: great"; OpenAPI swagger = Yaml.mapper().readValue(yaml, OpenAPI.class); SerializationMatchers.assertEqualsToYaml(swagger, yaml); } @Test(description = "should serialize string value") public void testStringValue() { final QueryParameter param = (QueryParameter) new QueryParameter().required(false); Schema schema = new Schema() .type("string"); schema.setDefault("false"); param.setSchema(schema); final String json = "{" + " \"in\":\"query\"," + " \"required\":false," + " \"schema\":{" + " \"type\":\"string\"," + " \"default\":\"false\"" + " }" + "}"; SerializationMatchers.assertEqualsToJson(param, json); } @Test(description = "should serialize boolean value") public void testBooleanValue() { final QueryParameter param = (QueryParameter) new QueryParameter().required(false); Schema schema = new Schema() .type("boolean"); schema.setDefault("false"); param.setSchema(schema); final String json = "{" + " \"in\":\"query\"," + " \"required\":false," + " \"schema\":{" + " \"type\":\"boolean\"," + " \"default\":\"false\"" + " }" + "}"; SerializationMatchers.assertEqualsToJson(param, json); } @Test(description = "should serialize long value") public void testLongValue() { final QueryParameter param = (QueryParameter) new QueryParameter().required(false); Schema schema = new IntegerSchema().format("int64"); schema.setDefault("1234"); param.setSchema(schema); final String json = "{" + " \"in\":\"query\"," + " \"required\":false," + " \"schema\":{" + " \"type\":\"integer\"," + " \"default\":1234," + " \"format\":\"int64\"" + " }" + "}"; SerializationMatchers.assertEqualsToJson(param, json); } @Test(description = "should serialize double value") public void testDoubleValue() { final QueryParameter param = new QueryParameter(); param.setSchema(new NumberSchema()._default(new BigDecimal("12.34")).format("double")); final String json = "{\"in\":\"query\",\"schema\":{\"type\":\"number\",\"format\":\"double\",\"default\":12.34}}"; SerializationMatchers.assertEqualsToJson(param, json); } @Test(description = "should serialize float value") public void testFloatValue() { final QueryParameter param = new QueryParameter(); param.setSchema(new NumberSchema()._default(new BigDecimal("12.34")).format("float")); final String json = "{\"in\":\"query\",\"schema\":{\"type\":\"number\",\"format\":\"float\",\"default\":12.34}}"; SerializationMatchers.assertEqualsToJson(param, json); } @Test(description = "should serialize incorrect boolean value as string") public void testIncorrectBoolean() { final QueryParameter param = (QueryParameter) new QueryParameter().required(false); Schema schema = new Schema() .type("boolean"); schema.setDefault("test"); param.setSchema(schema); final String json = "{" + " \"in\":\"query\"," + " \"required\":false," + " \"schema\":{" + " \"type\":\"boolean\"," + " \"default\":\"test\"" + " }" + "}"; SerializationMatchers.assertEqualsToJson(param, json); } @Test(description = "should not serialize incorrect long value") public void testIncorrectLong() { final QueryParameter param = (QueryParameter) new QueryParameter().required(false); Schema schema = new IntegerSchema().format("int64"); schema.setDefault("test"); param.setSchema(schema); final String json = "{" + " \"in\":\"query\"," + " \"required\":false," + " \"schema\":{" + " \"type\":\"integer\"," + " \"format\":\"int64\"" + " }" + "}"; SerializationMatchers.assertEqualsToJson(param, json); } @Test(description = "should not serialize incorrect double value") public void testIncorrectDouble() { final QueryParameter param = (QueryParameter) new QueryParameter().required(false); Schema schema = new NumberSchema().format("double"); schema.setDefault("test"); param.setSchema(schema); final String json = "{" + " \"in\":\"query\"," + " \"required\":false," + " \"schema\":{" + " \"type\":\"number\"," + " \"format\":\"double\"" + " }" + "}"; SerializationMatchers.assertEqualsToJson(param, json); } @Test(description = "should mark a parameter as readOnly") public void testReadOnlyParameter() throws Exception { final QueryParameter qp = new QueryParameter(); qp.setSchema(new StringSchema().readOnly(true)); final String json = "{" + " \"in\":\"query\"," + " \"schema\":{" + " \"type\":\"string\"," + " \"readOnly\":true" + " }" + "}"; SerializationMatchers.assertEqualsToJson(qp, json); } @Test(description = "should mark a parameter as to allow empty value") public void testAllowEmptyValueParameter() throws Exception { final Parameter qp = new QueryParameter().allowEmptyValue(true); final String json = "{\"in\":\"query\",\"allowEmptyValue\":true}"; SerializationMatchers.assertEqualsToJson(qp, json); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/ResponseExamplesTest.java ================================================ package io.swagger.v3.core.serialization; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.responses.ApiResponse; import org.testng.annotations.Test; import java.io.IOException; public class ResponseExamplesTest { @Test(description = "it should create a response") public void createResponse() throws IOException { final ApiResponse response = new ApiResponse() .content(new Content() .addMediaType("application/json", new MediaType() .addExamples("test", new Example().value("{\"name\":\"Fred\",\"id\":123456\"}")))); final String json = "{\n" + " \"content\" : {\n" + " \"application/json\" : {\n" + " \"examples\" : {\n" + " \"test\" : {\n" + " \"value\" : \"{\\\"name\\\":\\\"Fred\\\",\\\"id\\\":123456\\\"}\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(response, json); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/SchemaSerializationTest.java ================================================ package io.swagger.v3.core.serialization; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.JsonSchema; import org.testng.annotations.Test; import java.math.BigDecimal; import java.util.Arrays; import java.util.HashSet; public class SchemaSerializationTest { @Test public void serializeRefSchema3_1() { OpenAPI openAPI = new OpenAPI() .components(new Components() .addSchemas("Pet", new JsonSchema() .types(new HashSet<>(Arrays.asList("object"))) .format("whatever") ._if(new JsonSchema().type("string").types(new HashSet<>(Arrays.asList("string")))) .then(new JsonSchema().type("string").types(new HashSet<>(Arrays.asList("string")))) ._else(new JsonSchema().type("string").types(new HashSet<>(Arrays.asList("string")))) .minimum(BigDecimal.valueOf(1)) .addProperties("id", new JsonSchema().type("integer").types(new HashSet<>(Arrays.asList("integer")))) .addProperties("name", new JsonSchema().type("string").types(new HashSet<>(Arrays.asList("string")))) .addProperties("tag", new JsonSchema().type("string").types(new HashSet<>(Arrays.asList("string"))))) .addSchemas("AnotherPet", new JsonSchema() .title("Another Pet") .description("Another Pet for petstore referencing Pet schema") .$ref("#/components/schemas/Pet") .addProperties("category", new JsonSchema().types(new HashSet<>(Arrays.asList("string")))) .addProperties("photoUrl", new JsonSchema().types(new HashSet<>(Arrays.asList("string")))))); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.0.1\n" + "components:\n" + " schemas:\n" + " Pet:\n" + " type: object\n" + " format: whatever\n" + " if:\n" + " type: string\n" + " then:\n" + " type: string\n" + " else:\n" + " type: string\n" + " minimum: 1\n" + " properties:\n" + " id:\n" + " type: integer\n" + " name:\n" + " type: string\n" + " tag:\n" + " type: string\n" + " AnotherPet:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " description: Another Pet for petstore referencing Pet schema\n" + " properties:\n" + " category:\n" + " type: string\n" + " photoUrl:\n" + " type: string\n" + " title: Another Pet\n"); SerializationMatchers.assertEqualsToYaml(openAPI, "openapi: 3.0.1\n" + "components:\n" + " schemas:\n" + " Pet:\n" + " minimum: 1\n" + " properties:\n" + " id:\n" + " type: integer\n" + " name:\n" + " type: string\n" + " tag:\n" + " type: string\n" + " format: whatever\n" + " AnotherPet:\n" + " $ref: \"#/components/schemas/Pet\"\n"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/SecurityDefinitionTest.java ================================================ package io.swagger.v3.core.serialization; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.v3.core.oas.models.Person; import io.swagger.v3.core.util.ResourceUtils; import io.swagger.v3.core.util.TestUtils; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.OAuthFlow; import io.swagger.v3.oas.models.security.OAuthFlows; import io.swagger.v3.oas.models.security.Scopes; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; import org.testng.annotations.Test; import java.io.IOException; import java.util.Collections; import java.util.Map; import static org.testng.Assert.assertEquals; public class SecurityDefinitionTest { @Test(description = "it should serialize correctly security") public void serializeSecurity() throws IOException { final OpenAPI oas = TestUtils.deserializeJsonFileFromClasspath("specFiles/securityDefinitions.json", OpenAPI.class); final String json = ResourceUtils.loadClassResource(getClass(), "specFiles/securityDefinitions.json"); SerializationMatchers.assertEqualsToJson(oas, json); } @Test(description = "it should create a model with security requirements") public void createModelWithSecurityRequirements() throws IOException { final Schema personModel = ModelConverters.getInstance().read(Person.class).get("Person"); final Schema errorModel = ModelConverters.getInstance().read(Error.class).get("Error"); final Info info = new Info() .version("1.0.0") .title("Swagger Petstore"); final Contact contact = new Contact() .name("Swagger API Team") .email("foo@bar.baz") .url("http://swagger.io"); info.setContact(contact); final OpenAPI oas = new OpenAPI() .info(info) .addServersItem(new Server() .url("http://petstore.swagger.io")) .schema("Person", personModel) .schema("Error", errorModel); oas.schemaRequirement("githubAccessCode", new SecurityScheme() .flows(new OAuthFlows() .authorizationCode(new OAuthFlow() .scopes(new Scopes().addString("user:email", "Grants read access to a user’s email addresses."))))); final Operation get = new Operation() .summary("finds pets in the system") .description("a longer description") .addTagsItem("Pet Operations") .operationId("get pet by id"); get.addParametersItem(new Parameter() .in("query") .name("tags") .description("tags to filter by") .required(false) .schema(new StringSchema())); get.addParametersItem(new Parameter() .in("path") .name("petId") .description("pet to fetch") .schema(new IntegerSchema().format("int64"))); final ApiResponse response = new ApiResponse() .description("pets returned") .content(new Content().addMediaType("*/*", new MediaType().schema(new Schema().$ref("Person")))); final ApiResponse errorResponse = new ApiResponse() .description("error response") .content(new Content().addMediaType("*/*", new MediaType().schema(new Schema().$ref("Error")))); get.responses(new ApiResponses() .addApiResponse("200", response) .addApiResponse("default", errorResponse)) .addSecurityItem(new SecurityRequirement() .addList("internal_oauth2", "user:email")) .addSecurityItem(new SecurityRequirement() .addList("api_key")); oas.path("/pets", new PathItem().get(get)); final String json = ResourceUtils.loadClassResource(getClass(), "ModelWithSecurityRequirements.json"); SerializationMatchers.assertEqualsToJson(oas, json); } @Test(description = "Security Scheme deserialization should not remove extensions") public void doNotRemoveExtensions() { final SecurityScheme securityScheme = TestUtils.deserializeJsonFileFromClasspath("specFiles/securitySchemaWithExtension.json", SecurityScheme.class); final Map extensions = securityScheme.getExtensions(); final Map expected = Collections.singletonMap("x-custom", Collections.singletonMap("key-string", "value-one")); assertEquals(extensions, expected); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/YamlSerializerTest.java ================================================ package io.swagger.v3.core.serialization; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.core.util.Yaml; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; public class YamlSerializerTest { @Test public void testMultiLineYaml() throws Exception { final String yaml = "multiLineString: |\n" + " \"hello multiple lines\n" + " in my content without\n" + " any problem\"\n"; JsonNode node = Yaml.mapper().readValue(yaml, JsonNode.class); String serializedYaml = Yaml.pretty(node); assertEquals(serializedYaml, yaml); } @Test public void testQuotedStrings() throws Exception { final String yaml = "singleLineUnquotedString: Look ma no quotes\n"; JsonNode node = Yaml.mapper().readValue(yaml, JsonNode.class); String serializedYaml = Yaml.pretty(node); assertEquals(serializedYaml, yaml); } @Test public void testPreserveQuotesOnNumbers() throws Exception { final String yaml = "quotedNumber: \"3.0\"\n"; JsonNode node = Yaml.mapper().readValue(yaml, JsonNode.class); String serializedYaml = Yaml.pretty(node); assertEquals(serializedYaml, yaml); } @Test public void testPreserveNoQuotesOnNumbers() throws Exception { final String yaml = "unquotedNumber: 4.0\n"; JsonNode node = Yaml.mapper().readValue(yaml, JsonNode.class); String serializedYaml = Yaml.pretty(node); assertEquals(serializedYaml, yaml); } @Test public void testPreserveNoQuotesOnNonNumbers() throws Exception { final String yaml = "unquotedNumber: 4.0.0\n"; JsonNode node = Yaml.mapper().readValue(yaml, JsonNode.class); String serializedYaml = Yaml.pretty(node); assertEquals(serializedYaml, yaml); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/auth/AuthSerializationTest.java_ ================================================ package io.swagger.v3.core.serialization.auth; import io.swagger.v3.core.matchers.SerializationMatchers; import io.swagger.models.auth.ApiKeyAuthDefinition; import io.swagger.models.auth.BasicAuthDefinition; import io.swagger.models.auth.In; import io.swagger.models.auth.OAuth2Definition; import org.testng.annotations.Test; import java.io.IOException; public class AuthSerializationTest { @Test(description = "it should convert serialize a basic auth model") public void testBasicAuth() throws IOException { final BasicAuthDefinition auth = new BasicAuthDefinition(); final String json = "{\"type\":\"basic\"}"; SerializationMatchers.assertEqualsToJson(auth, json); } @Test(description = "it should convert serialize a header key model") public void testHeaderKeyToJson() throws IOException { final ApiKeyAuthDefinition auth = new ApiKeyAuthDefinition() .name("api-key") .in(In.HEADER); final String json = "{\"type\":\"apiKey\",\"name\":\"api-key\",\"in\":\"header\"}"; SerializationMatchers.assertEqualsToJson(auth, json); } @Test(description = "it should convert serialize a header key model to yaml") public void testHeaderKeyToYaml() throws IOException { final ApiKeyAuthDefinition auth = new ApiKeyAuthDefinition() .name("api-key") .in(In.HEADER); final String yaml = "---\n" + "type: \"apiKey\"\n" + "name: \"api-key\"\n" + "in: \"header\""; SerializationMatchers.assertEqualsToYaml(auth, yaml); } @Test(description = "it should convert serialize an oauth2 implicit flow model") public void testImplicitAuth() throws IOException { final OAuth2Definition auth = new OAuth2Definition() .implicit("http://foo.com/authorization"); final String json = "{\"type\":\"oauth2\",\"authorizationUrl\":\"http://foo.com/authorization\",\"flow\":\"implicit\"}"; SerializationMatchers.assertEqualsToJson(auth, json); } @Test(description = "it should convert serialize an oauth2 password flow model") public void testPasswordAuth() throws IOException { final OAuth2Definition auth = new OAuth2Definition() .password("http://foo.com/token"); final String json = "{\"type\":\"oauth2\",\"tokenUrl\":\"http://foo.com/token\",\"flow\":\"password\"}"; SerializationMatchers.assertEqualsToJson(auth, json); } @Test(description = "it should convert serialize an oauth2 application flow model") public void testApplicationAuth() throws IOException { final OAuth2Definition auth = new OAuth2Definition() .application("http://foo.com/token"); final String json = "{\"type\":\"oauth2\",\"tokenUrl\":\"http://foo.com/token\",\"flow\":\"application\"}"; SerializationMatchers.assertEqualsToJson(auth, json); } @Test(description = "it should convert serialize an oauth2 accessCode flow model") public void testaAcessCode() throws IOException { final OAuth2Definition auth = new OAuth2Definition() .accessCode("http://foo.com/authorizationUrl", "http://foo.com/token"); final String json = "{\n" + " \"type\":\"oauth2\",\n" + " \"authorizationUrl\":\"http://foo.com/authorizationUrl\",\n" + " \"tokenUrl\":\"http://foo.com/token\",\n" + " \"flow\":\"accessCode\"\n" + "}"; SerializationMatchers.assertEqualsToJson(auth, json); } @Test(description = "it should convert serialize an oauth2 implicit flow model with scopes") public void testImplicitWithScopes() throws IOException { final OAuth2Definition auth = new OAuth2Definition() .implicit("http://foo.com/authorization") .scope("email", "read your email"); final String json = "{\n" + " \"type\":\"oauth2\",\n" + " \"authorizationUrl\":\"http://foo.com/authorization\",\n" + " \"flow\":\"implicit\",\n" + " \"scopes\":{\n" + " \"email\":\"read your email\"\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(auth, json); } @Test(description = "it should convert serialize an oauth2 password flow model with scopes") public void testPasswordWithScopes() throws IOException { final OAuth2Definition auth = new OAuth2Definition() .password("http://foo.com/token") .scope("email", "read your email"); final String json = "{\n" + " \"type\":\"oauth2\",\n" + " \"tokenUrl\":\"http://foo.com/token\",\n" + " \"flow\":\"password\",\n" + " \"scopes\":{\n" + " \"email\":\"read your email\"\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(auth, json); } @Test(description = "it should convert serialize an oauth2 application flow model with scopes") public void testApplicationWithScopes() throws IOException { final OAuth2Definition auth = new OAuth2Definition() .application("http://foo.com/token") .scope("email", "read your email"); final String json = "{\n" + " \"type\":\"oauth2\",\n" + " \"tokenUrl\":\"http://foo.com/token\",\n" + " \"flow\":\"application\",\n" + " \"scopes\":{\n" + " \"email\":\"read your email\"\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(auth, json); } @Test(description = "it should convert serialize an oauth2 accessCode flow model with scopes") public void testAccessCodeWithScopes() throws IOException { final OAuth2Definition auth = new OAuth2Definition() .accessCode("http://foo.com/authorizationUrl", "http://foo.com/token") .scope("email", "read your email"); final String json = "{\n" + " \"type\":\"oauth2\",\n" + " \"authorizationUrl\":\"http://foo.com/authorizationUrl\",\n" + " \"tokenUrl\":\"http://foo.com/token\",\n" + " \"flow\":\"accessCode\",\n" + " \"scopes\":{\n" + " \"email\":\"read your email\"\n" + " }\n" + "}"; SerializationMatchers.assertEqualsToJson(auth, json); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/properties/PropertySerializationTest.java ================================================ package io.swagger.v3.core.serialization.properties; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.JsonAssert; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.BooleanSchema; import io.swagger.v3.oas.models.media.DateSchema; import io.swagger.v3.oas.models.media.DateTimeSchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.MapSchema; import io.swagger.v3.oas.models.media.NumberSchema; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; public class PropertySerializationTest { private final ObjectMapper m = Json.mapper(); @Test(description = "it should serialize a BooleanSchema") public void serializeBooleanSchema() throws IOException { final BooleanSchema p = new BooleanSchema() ._default(true); final String json = "{\"type\":\"boolean\",\"default\":true}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a BooleanSchema") public void deserializeBooleanSchema() throws IOException { final String json = "{\"type\":\"boolean\",\"default\":false}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "boolean"); assertNull(p.getFormat()); assertEquals(p.getClass(), BooleanSchema.class); assertEquals(((BooleanSchema) p).getDefault(), Boolean.FALSE); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a DateProperty") public void serializeDateProperty() throws IOException { final DateSchema p = new DateSchema(); final String json = "{\"type\":\"string\",\"format\":\"date\"}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a DateProperty") public void deserializeDateProperty() throws IOException { final String json = "{\"type\":\"string\",\"format\":\"date\"}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "string"); assertEquals(p.getFormat(), "date"); assertEquals(p.getClass(), DateSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a DateTimeProperty") public void serializeDateTimeProperty() throws IOException { final DateTimeSchema p = new DateTimeSchema(); final String json = "{\"type\":\"string\",\"format\":\"date-time\"}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a DateTimeProperty") public void deserializeDateTimeProperty() throws IOException { final String json = "{\"type\":\"string\",\"format\":\"date-time\"}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "string"); assertEquals(p.getFormat(), "date-time"); assertEquals(p.getClass(), DateTimeSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a DoubleProperty") public void serializeDoubleProperty() throws IOException { final NumberSchema p = new NumberSchema() ._default(new BigDecimal("3.14159")); p.format("double"); final String json = "{\"type\":\"number\",\"format\":\"double\",\"default\":3.14159}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a DoubleProperty") public void deserializeDoubleProperty() throws IOException { final String json = "{\"type\":\"number\",\"format\":\"double\"}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "number"); assertEquals(p.getFormat(), "double"); assertEquals(p.getClass(), NumberSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a FloatProperty") public void serializeFloatProperty() throws IOException { final NumberSchema p = new NumberSchema() ._default(new BigDecimal("1.2")); p.format("float"); final String json = "{\"type\":\"number\",\"format\":\"float\",\"default\":1.2}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a FloatProperty") public void deserializeFloatProperty() throws IOException { final String json = "{\"type\":\"number\",\"format\":\"float\"}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "number"); assertEquals(p.getFormat(), "float"); assertEquals(p.getClass(), NumberSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize an IntegerProperty") public void serializeIntegerProperty() throws IOException { final IntegerSchema p = new IntegerSchema() ._default(32); final String json = "{\"type\":\"integer\",\"format\":\"int32\",\"default\":32}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a IntegerProperty") public void deserializeIntegerProperty() throws IOException { final String json = "{\"type\":\"integer\",\"format\":\"int32\"}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "integer"); assertEquals(p.getFormat(), "int32"); assertEquals(p.getClass(), IntegerSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a LongProperty") public void serializeLongProperty() throws IOException { final IntegerSchema p = new IntegerSchema() .format("int64") ._default(8675309); final String json = "{\"type\":\"integer\",\"format\":\"int64\",\"default\":8675309}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a LongProperty") public void deserializeLongProperty() throws IOException { final String json = "{\"type\":\"integer\",\"format\":\"int64\"}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "integer"); assertEquals(p.getFormat(), "int64"); assertEquals(p.getClass(), IntegerSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a string MapProperty") public void serializeStringMapProperty() throws IOException { final Schema p = new MapSchema().additionalProperties(new StringSchema()); final String json = "{\"type\":\"object\",\"additionalProperties\":{\"type\":\"string\"}}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a string MapProperty") public void deserializeStringMapProperty() throws IOException { final String json = "{\"type\":\"object\",\"additionalProperties\":{\"type\":\"string\"}}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "object"); assertEquals(p.getClass(), MapSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a integer MapProperty") public void serializeIntegerMapProperty() throws IOException { final Schema p = new MapSchema().additionalProperties(new IntegerSchema()); final String json = "{\"type\":\"object\",\"additionalProperties\":{\"type\":\"integer\",\"format\":\"int32\"}}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a integer MapProperty") public void deserializeIntegerMapProperty() throws IOException { final String json = "{\"type\":\"object\",\"additionalProperties\":{\"type\":\"integer\",\"format\":\"int32\"}}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "object"); assertEquals(p.getClass(), MapSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a long MapProperty") public void serializeLongMapProperty() throws IOException { final Schema p = new MapSchema().additionalProperties(new IntegerSchema().format("int64")); final String json = "{\"type\":\"object\",\"additionalProperties\":{\"type\":\"integer\",\"format\":\"int64\"}}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a long MapProperty") public void deserializeLongMapProperty() throws IOException { final String json = "{\"type\":\"object\",\"additionalProperties\":{\"type\":\"integer\",\"format\":\"int64\"}}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "object"); assertEquals(p.getClass(), MapSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a RefProperty") public void serializeRefProperty() throws IOException { final Schema p = new Schema().$ref("#/definitions/Dog"); final String json = "{\"$ref\":\"#/definitions/Dog\"}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a RefProperty") public void deserializeRefProperty() throws IOException { final String json = "{\"$ref\":\"#/definitions/Dog\"}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getClass(), Schema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a StringProperty") public void serializeStringProperty() throws IOException { final StringSchema p = new StringSchema() ._default("Bob"); final String json = "{\"type\":\"string\",\"default\":\"Bob\"}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a StringProperty") public void deserializeStringProperty() throws IOException { final String json = "{\"type\":\"string\"}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "string"); assertEquals(p.getClass(), StringSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a StringProperty with enums") public void serializeEnumStringProperty() throws IOException { final StringSchema p = new StringSchema(); p._enum(new ArrayList() {{ this.add("a"); this.add("b"); }}); final String json = "{\"type\":\"string\",\"enum\":[\"a\",\"b\"]}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a StringProperty with enums") public void deserializeEnumStringProperty() throws IOException { final String json = "{\"type\":\"string\",\"enum\":[\"a\",\"b\"]}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "string"); List _enum = ((StringSchema) p).getEnum(); assertNotNull(_enum); assertEquals(_enum, Arrays.asList("a", "b")); assertEquals(p.getClass(), StringSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize an IntegerProperty with enums") public void deserializeEnumIntegerProperty() throws IOException { final String json = "{\"type\":\"integer\",\"format\":\"int32\",\"enum\":[1,2]}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "integer"); List _enum = ((IntegerSchema) p).getEnum(); assertNotNull(_enum); assertEquals(_enum, Arrays.asList(1, 2)); assertEquals(p.getClass(), IntegerSchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a string array property") public void serializeArrayStringProperty() throws IOException { final Schema p = new ArraySchema().items(new StringSchema()); final String json = "{\"type\":\"array\",\"items\":{\"type\":\"string\"}}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize a string array property") public void deserializeArrayStringProperty() throws IOException { final String json = "{\"type\":\"array\",\"items\":{\"type\":\"string\"}}"; final Schema p = m.readValue(json, Schema.class); assertEquals(p.getType(), "array"); assertEquals(p.getClass(), ArraySchema.class); JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a string property with readOnly set") public void serializeReadOnlyStringProperty() throws IOException { final Schema p = new StringSchema().readOnly(true); final String json = "{\"type\":\"string\",\"readOnly\":true}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize a string property with readOnly unset") public void deserializeNotReadOnlyStringProperty() throws IOException { final StringSchema p = new StringSchema(); p.setReadOnly(false); final String json = "{\"type\":\"string\",\"readOnly\":false}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should serialize an object property with required set") public void serializeObjectPropertyWithRequiredProperties() throws IOException { final Schema p = new ObjectSchema() .addProperties("stringProperty", new StringSchema()); p.required(Arrays.asList("stringProperty")); final String json = "{\"required\":[\"stringProperty\"],\"type\":\"object\",\"properties\":{\"stringProperty\":{\"type\":\"string\"}}}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } @Test(description = "it should deserialize an object property with required set") public void deserializeObjectPropertyWithRequiredProperties() throws IOException { final Schema p = new ObjectSchema() .addProperties("stringProperty", new StringSchema()); p.required(Arrays.asList("stringProperty")); final String json = "{\"type\":\"object\",\"properties\":{\"stringProperty\":{\"type\":\"string\"}},\"required\":[\"stringProperty\"]}"; JsonAssert.assertJsonEquals(m, m.writeValueAsString(p), json); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/AnnotationsUtilsTest.java ================================================ package io.swagger.v3.core.util; import com.google.common.collect.ImmutableMap; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; import java.io.Serializable; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.util.Date; import java.util.Map; import java.util.Optional; import java.util.UUID; import static io.swagger.v3.oas.annotations.media.Schema.DEFAULT_SENTINEL; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertTrue; public class AnnotationsUtilsTest { @DataProvider private Object[][] expectedSchemaFromTypes() { return new Object[][]{ {String.class, ImmutableMap.of("type", "string")}, {Character.class, ImmutableMap.of("type", "string")}, {Boolean.class, ImmutableMap.of("type", "boolean")}, {Byte.class, ImmutableMap.of("type", "string", "format", "byte")}, {URI.class, ImmutableMap.of("type", "string", "format", "uri")}, {URL.class, ImmutableMap.of("type", "string", "format", "url")}, {UUID.class, ImmutableMap.of("type", "string", "format", "uuid")}, {Short.class, ImmutableMap.of("type", "integer", "format", "int32")}, {Integer.class, ImmutableMap.of("type", "integer", "format", "int32")}, {Long.class, ImmutableMap.of("type", "integer", "format", "int64")}, {Float.class, ImmutableMap.of("type", "number", "format", "float")}, {Double.class, ImmutableMap.of("type", "number", "format", "double")}, {BigInteger.class, ImmutableMap.of("type", "integer")}, {BigDecimal.class, ImmutableMap.of("type", "number")}, {Number.class, ImmutableMap.of("type", "number")}, {Date.class, ImmutableMap.of("type", "string", "format", "date-time")}, {File.class, ImmutableMap.of("type", "string", "format", "binary")}, {Object.class, ImmutableMap.of("type", "object")}, {DummyClass.class, ImmutableMap.of("$ref", "#/components/schemas/DummyClass")} }; } @Test(dataProvider = "expectedSchemaFromTypes") public void resolveSchemaFromType(Class aClass, Map expected) { Schema schema = AnnotationsUtils.resolveSchemaFromType(aClass, new Components(), null); assertEquals(schema.getType(), expected.get("type")); assertEquals(schema.getFormat(), expected.get("format")); assertEquals(schema.get$ref(), expected.get("$ref")); } @DataProvider private Object[][] expectedSchemaFromTypeAndFormat() { return new Object[][]{ {"byteType", ImmutableMap.of("type", "string", "format", "byte")}, {"binaryType", ImmutableMap.of("type", "string", "format", "binary")}, {"emailType", ImmutableMap.of("type", "string", "format", "email")}, {"dummyType", ImmutableMap.of("$ref", "#/components/schemas/DummyClass")} }; } @Test(dataProvider = "expectedSchemaFromTypeAndFormat") public void getSchema(String methodName, Map expected) throws NoSuchMethodException { final Method method = getClass().getDeclaredMethod(methodName); Content annotationContent = method.getAnnotation(ApiResponse.class).content()[0]; Optional schema = AnnotationsUtils.getSchema(annotationContent, new Components(), null, false); assertTrue(schema.isPresent()); assertEquals(schema.get().getType(), expected.get("type")); assertEquals(schema.get().getFormat(), expected.get("format")); assertEquals(schema.get().get$ref(), expected.get("$ref")); } @ApiResponse(content = @Content(schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = Byte.class))) private void byteType() { } @ApiResponse(content = @Content(schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = Byte.class, format = "binary"))) private void binaryType() { } @ApiResponse(content = @Content(schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = String.class, format = "email"))) private void emailType() { } @ApiResponse(content = @Content(schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = DummyClass.class))) private void dummyType() { } class DummyClass implements Serializable {} static class ExampleHolder { @io.swagger.v3.oas.annotations.media.Schema(type = "string", example = "5 lacs per annum") String value; } @Test public void testExampleStartingWithNumberShouldBeString() throws Exception { io.swagger.v3.oas.annotations.media.Schema schemaAnnotation = ExampleHolder.class .getDeclaredField("value") .getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); Optional schema = AnnotationsUtils.getSchemaFromAnnotation( schemaAnnotation, null, null, false, null, Schema.SchemaResolution.DEFAULT, null ); assertTrue(schema.isPresent()); assertEquals(schema.get().getExample(), "5 lacs per annum"); } // --- mergeSchemaAnnotations defaultValue tests --- @io.swagger.v3.oas.annotations.media.Schema(description = "type-level description") static class TypeWithDescriptionOnly {} static class FieldHolderWithDefault { @io.swagger.v3.oas.annotations.media.Schema(defaultValue = "myDefault") TypeWithDescriptionOnly field; } static class FieldHolderWithEmptyDefault { @io.swagger.v3.oas.annotations.media.Schema(defaultValue = "") TypeWithDescriptionOnly field; } @io.swagger.v3.oas.annotations.media.Schema(defaultValue = "typeDefault") static class TypeWithDefault {} static class FieldHolderWithTypeDefault { @io.swagger.v3.oas.annotations.media.Schema(description = "field-level description") TypeWithDefault field; } @Test public void mergedDefaultValueShouldUsePatchWhenMasterHasSentinel() throws Exception { io.swagger.v3.oas.annotations.media.Schema master = TypeWithDescriptionOnly.class.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema patch = FieldHolderWithDefault.class.getDeclaredField("field") .getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema merged = AnnotationsUtils.mergeSchemaAnnotations(master, patch); assertEquals(merged.defaultValue(), "myDefault", "When master has no defaultValue (sentinel) and patch has one, the patch value should win"); } @Test public void mergedDefaultValueShouldUseMasterWhenMasterHasRealValue() throws Exception { io.swagger.v3.oas.annotations.media.Schema master = TypeWithDefault.class.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema patch = FieldHolderWithDefault.class.getDeclaredField("field") .getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema merged = AnnotationsUtils.mergeSchemaAnnotations(master, patch); assertEquals(merged.defaultValue(), "typeDefault", "When master has a real defaultValue, it should take precedence over patch"); } @Test public void mergedDefaultValueShouldReturnSentinelWhenBothHaveSentinel() throws Exception { io.swagger.v3.oas.annotations.media.Schema master = TypeWithDescriptionOnly.class.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema patch = FieldHolderWithTypeDefault.class.getDeclaredField("field") .getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema merged = AnnotationsUtils.mergeSchemaAnnotations(master, patch); assertEquals(merged.defaultValue(), DEFAULT_SENTINEL, "When both master and patch have sentinel, the merged result should also have sentinel"); } @Test public void mergedDefaultValueShouldUseEmptyStringFromPatch() throws Exception { io.swagger.v3.oas.annotations.media.Schema master = TypeWithDescriptionOnly.class.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema patch = FieldHolderWithEmptyDefault.class.getDeclaredField("field") .getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema merged = AnnotationsUtils.mergeSchemaAnnotations(master, patch); assertEquals(merged.defaultValue(), "", "When master has sentinel and patch has empty string, empty string should win"); } @Test public void sentinelShouldNeverAppearInResolvedSchema() throws Exception { io.swagger.v3.oas.annotations.media.Schema master = TypeWithDescriptionOnly.class.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema patch = FieldHolderWithDefault.class.getDeclaredField("field") .getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); io.swagger.v3.oas.annotations.media.Schema merged = AnnotationsUtils.mergeSchemaAnnotations(master, patch); assertNotEquals(merged.defaultValue(), DEFAULT_SENTINEL, "Sentinel should never be the result when patch has a real defaultValue"); Optional resolvedSchema = AnnotationsUtils.getSchemaFromAnnotation( merged, null, null, false, null, Schema.SchemaResolution.DEFAULT, null); assertTrue(resolvedSchema.isPresent()); assertNotEquals(resolvedSchema.get().getDefault(), DEFAULT_SENTINEL, "Sentinel value must never appear in resolved schema default"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/JsonAssert.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import static org.testng.Assert.assertTrue; public final class JsonAssert { private JsonAssert() { } /** * Asserts that two JSON strings are semantically equal, ignoring key order. * This version uses a default failure message. * * @param mapper The ObjectMapper to use for parsing. * @param expectedJson The expected JSON/YAML string. * @param actualJson The actual JSON/YAML string. */ public static void assertJsonEquals(ObjectMapper mapper, String expectedJson, String actualJson) { assertJsonEquals(mapper, expectedJson, actualJson, "The JSON structures are not equal."); } /** * This version allows for a custom failure message. * * @param mapper The ObjectMapper to use for parsing. * @param expectedJson The expected JSON/YAML string. * @param actualJson The actual JSON/YAML string. * @param message The custom message to display if the assertion fails. */ public static void assertJsonEquals(ObjectMapper mapper, String expectedJson, String actualJson, String message) { try { JsonNode expectedNode = mapper.readTree(expectedJson); JsonNode actualNode = mapper.readTree(actualJson); assertTrue(expectedNode.equals(actualNode), message); } catch (Exception e) { throw new RuntimeException(e); } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/OutputReplacer.java ================================================ package io.swagger.v3.core.util; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; /** * The OutputReplacer enumerator helps to run a code with a custom output stream. */ public enum OutputReplacer { /** * The "standard" output stream. */ OUT { @Override PrintStream getOutputStream() { return System.out; } @Override void setOutputStream(PrintStream outputStream) { System.setOut(outputStream); } }, /** * The "standard" error output stream. */ ERROR { @Override PrintStream getOutputStream() { return System.err; } @Override void setOutputStream(PrintStream outputStream) { System.setErr(outputStream); } }; /** * Runs a code with a custom output stream. * * @param function is code to run * @return is output stream as string */ public String run(Function function) { final PrintStream out = getOutputStream(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final PrintStream capture = new PrintStream(outputStream); try { setOutputStream(capture); PrettyPrintHelper.setOverride(message -> { capture.println(message); capture.flush(); }); function.run(); } finally { PrettyPrintHelper.clearOverride(); setOutputStream(out); capture.close(); } try { return outputStream.toString(StandardCharsets.UTF_8.name()); } catch (UnsupportedEncodingException ex) { throw new IllegalStateException(ex); } } abstract PrintStream getOutputStream(); abstract void setOutputStream(PrintStream printStream); public interface Function { void run(); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/PathUtilsTest.java ================================================ package io.swagger.v3.core.util; import org.testng.annotations.Test; import java.util.HashMap; import java.util.Map; import static org.testng.Assert.assertEquals; public class PathUtilsTest { @Test(description = "parse regex with slash inside it from issue 1153") public void parseRegexWithSlashInside() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("/{itemId: [0-9]{4}/[0-9]{2}/[0-9]{2}/[0-9]{2}/[0-9]{2}/[0-9]{2}/[0-9]{3}/[A-Za-z0-9]+}", regexMap); assertEquals(path, "/{itemId}"); assertEquals(regexMap.get("itemId"), "[0-9]{4}/[0-9]{2}/[0-9]{2}/[0-9]{2}/[0-9]{2}/[0-9]{2}/[0-9]{3}/[A-Za-z0-9]+"); } @Test(description = "parse two part path with one param") public void parseTwoPartPathWithOneParam() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("/api/{itemId: [0-9]{4}/[0-9]{2,4}/[A-Za-z0-9]+}", regexMap); assertEquals(path, "/api/{itemId}"); assertEquals(regexMap.get("itemId"), "[0-9]{4}/[0-9]{2,4}/[A-Za-z0-9]+"); } @Test(description = "parse two part path with two params and white spaces around") public void parseTwoPartPathWithTwoParams() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("/{itemId: [0-9]{4}/[A-Za-z0-9]+}/{ api : [aA-zZ]+ }", regexMap); assertEquals(path, "/{itemId}/{api}"); assertEquals(regexMap.get("itemId"), "[0-9]{4}/[A-Za-z0-9]+"); assertEquals(regexMap.get("api"), "[aA-zZ]+"); } @Test(description = "parse simple path") public void parseSimplePath() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("/api/itemId", regexMap); assertEquals(path, "/api/itemId"); assertEquals(regexMap.size(), 0); } @Test(description = "parse path with param without regex") public void parsePathWithoutRegex() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("/api/{name}", regexMap); assertEquals(path, "/api/{name}"); assertEquals(regexMap.size(), 0); } @Test(description = "parse path with two params in one part") public void parsePathWithTwoParamsInOnePart() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("/{a:\\w+}-{b:\\w+}/c", regexMap); assertEquals(path, "/{a}-{b}/c"); assertEquals(regexMap.get("a"), "\\w+"); assertEquals(regexMap.get("b"), "\\w+"); } @Test(description = "parse path like /swagger.{json|yaml}") public void test() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("/swagger.{json|yaml}", regexMap); assertEquals(path, "/swagger.{json|yaml}"); assertEquals(regexMap.size(), 0); } @Test(description = "parse path with many braces and slashes iside") public void parsePathWithBracesAndSlashes() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("/api/{regex:/(?!\\{\\})\\w*|/\\{\\w+:*([^\\{\\}]*(\\{.*\\})*)*\\}}", regexMap); assertEquals(path, "/api/{regex}"); assertEquals(regexMap.get("regex"), "/(?!\\{\\})\\w*|/\\{\\w+:*([^\\{\\}]*(\\{.*\\})*)*\\}"); } @Test(description = "collect path") public void collectPath() { final String path = PathUtils.collectPath("api", "/users/", "{userId}/"); assertEquals(path, "/api/users/{userId}"); } @Test(description = "collect path with many slashes inside") public void collectPathWithSlashesInside() { final String path = PathUtils.collectPath("///api/users///", "///getUser///", "/ /"); assertEquals(path, "/api/users/getUser"); } @Test(description = "not fail when passed path is null") public void testNullPath() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath(null, regexMap); assertEquals(path, null); } @Test(description = "not fail when regex is not valid") public void testInvalidRegex() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("/api/{fail: [a-z]", regexMap); assertEquals(path, null); } @Test(description = "not fail when passed path is empty") public void testEmptyPath() { final Map regexMap = new HashMap(); final String path = PathUtils.parsePath("", regexMap); assertEquals(path, "/"); } @Test(description = "not fail when passed path is null") public void testNullCollectedPath() { final String path = PathUtils.collectPath(null, null); assertEquals(path, "/"); } @Test(description = "not fail when passed path is empty") public void testEmptyCollectedPath() { final String path = PathUtils.collectPath(""); assertEquals(path, "/"); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/ReferenceTypeUtilsTest.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; import io.swagger.v3.core.converter.AnnotatedType; import org.testng.annotations.Test; import java.lang.reflect.Type; import java.math.BigDecimal; import java.util.concurrent.atomic.AtomicReference; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; /** * Unit test cases for {@link ReferenceTypeUtils} */ public class ReferenceTypeUtilsTest { @Test(description = "AtomicReference should be reference type") public void testIsReferenceTypeWithAtomicReference() { final JavaType referredType = TypeFactory.defaultInstance().constructType(String.class); final Class rawType = AtomicReference.class; final JavaType atomicReferenceType = TypeFactory.defaultInstance().constructReferenceType(rawType, referredType); final boolean actualIsReferenceType = ReferenceTypeUtils._isReferenceType(atomicReferenceType); assertTrue(actualIsReferenceType, rawType.getCanonicalName() + " should be reference type but was not."); } @Test(description = "AtomicReference JavaType should be unwrapped") public void testUnwrapWithAtomicReferenceAndJavaType() { final JavaType expectedReferredType = TypeFactory.defaultInstance().constructType(String.class); final Class rawType = AtomicReference.class; final JavaType atomicReferenceType = TypeFactory.defaultInstance().constructReferenceType(rawType, expectedReferredType); final AnnotatedType actualUnwrappedType = ReferenceTypeUtils.unwrapReference(new AnnotatedType(atomicReferenceType)); assertEquals(actualUnwrappedType.getType(), expectedReferredType, rawType.getCanonicalName() + "Reference type not correctly unwrapped"); } @Test(description = "AtomicReference should be unwrapped when read from Java bean") public void testUnwrapWithAtomicReferenceMemberFromJavaBean() throws Exception { final JavaType expectedReferredType = TypeFactory.defaultInstance().constructType(BigDecimal.class); final Type genericType = TypeWithAtomicReferenceMember.class.getDeclaredField("member").getGenericType(); final AnnotatedType actualUnwrappedType = ReferenceTypeUtils.unwrapReference(new AnnotatedType(genericType)); assertEquals(actualUnwrappedType.getType(), expectedReferredType, genericType.getTypeName() + "Reference type not correctly unwrapped"); } @SuppressWarnings("unused") private static final class TypeWithAtomicReferenceMember { AtomicReference member; public AtomicReference getMember() { return member; } public void setMember(AtomicReference member) { this.member = member; } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/ResourceUtils.java ================================================ package io.swagger.v3.core.util; import org.apache.commons.io.IOUtils; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; public class ResourceUtils { public static String loadClassResource(Class cls, String name) throws IOException { InputStream in = null; try { in = cls.getClassLoader().getResourceAsStream(name); return IOUtils.toString(in, StandardCharsets.UTF_8); } finally { IOUtils.closeQuietly(in); } } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/TestUtils.java ================================================ package io.swagger.v3.core.util; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.io.IOUtils; import java.io.IOException; import java.io.InputStream; /** * Created by russellb337 on 7/31/15. */ public class TestUtils { private static T deserializeFileFromClasspath(String path, Class type, ObjectMapper objectMapper) { final InputStream resource = TestUtils.class.getClassLoader().getResourceAsStream(path); String contents; if (resource == null) { throw new RuntimeException("Could not find file on the classpath: " + path); } try { contents = IOUtils.toString(resource); } catch (IOException e) { throw new RuntimeException("could not read from file " + path, e); } try { T result = objectMapper.readValue(contents, type); return result; } catch (IOException e) { throw new RuntimeException("Could not deserialize contents into type: " + type, e); } } public static T deserializeJsonFileFromClasspath(String path, Class type) { return deserializeFileFromClasspath(path, type, Json.mapper()); } public static T deserializeYamlFileFromClasspath(String path, Class type) { return deserializeFileFromClasspath(path, type, Yaml.mapper()); } public static String normalizeLineEnds(String s) { return s.replace("\r\n", "\n").replace('\r', '\n'); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/ValidationAnnotationsUtilsTest.java ================================================ package io.swagger.v3.core.util; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.NumberSchema; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import javax.validation.constraints.*; import java.math.BigDecimal; import static org.testng.Assert.*; public class ValidationAnnotationsUtilsTest { private Size createSizeAnnotation(final int min, final int max) { return new Size() { @Override public Class[] groups() { return new Class[0]; } @Override public String message() { return ""; } @Override public Class[] payload() { return new Class[0]; } @Override public int min() { return min; } @Override public int max() { return max; } @Override public Class annotationType() { return Size.class; } }; } private Min createMinAnnotation(final long value) { return new Min() { @Override public Class[] groups() { return new Class[0]; } @Override public String message() { return ""; } @Override public Class[] payload() { return new Class[0]; } @Override public long value() { return value; } @Override public Class annotationType() { return Min.class; } }; } private Max createMaxAnnotation(final long value) { return new Max() { @Override public Class[] groups() { return new Class[0]; } @Override public String message() { return ""; } @Override public Class[] payload() { return new Class[0]; } @Override public long value() { return value; } @Override public Class annotationType() { return Max.class; } }; } private DecimalMin createDecimalMinAnnotation(final String value, final boolean inclusive) { return new DecimalMin() { @Override public Class[] groups() { return new Class[0]; } @Override public String message() { return ""; } @Override public Class[] payload() { return new Class[0]; } @Override public String value() { return value; } @Override public boolean inclusive() { return inclusive; } @Override public Class annotationType() { return DecimalMin.class; } }; } private DecimalMax createDecimalMaxAnnotation(final String value, final boolean inclusive) { return new DecimalMax() { @Override public Class[] groups() { return new Class[0]; } @Override public String message() { return ""; } @Override public Class[] payload() { return new Class[0]; } @Override public String value() { return value; } @Override public boolean inclusive() { return inclusive; } @Override public Class annotationType() { return DecimalMax.class; } }; } private Pattern createPatternAnnotation(final String regexp) { return new Pattern() { @Override public Class[] groups() { return new Class[0]; } @Override public String message() { return ""; } @Override public Class[] payload() { return new Class[0]; } @Override public String regexp() { return regexp; } @Override public Pattern.Flag[] flags() { return new Pattern.Flag[0]; } @Override public Class annotationType() { return Pattern.class; } }; } private Email createEmailAnnotation() { return new Email() { @Override public Class[] groups() { return new Class[0]; } @Override public String message() { return ""; } @Override public Class[] payload() { return new Class[0]; } @Override public String regexp() { return ""; } @Override public Pattern.Flag[] flags() { return new Pattern.Flag[0]; } @Override public Class annotationType() { return Email.class; } }; } @Test public void testApplyNotEmptyConstraintOnArraySchema() { Schema schema = new ArraySchema(); boolean modified = ValidationAnnotationsUtils.applyNotEmptyConstraint(schema, null, null); assertTrue(modified); assertEquals(schema.getMinItems(), Integer.valueOf(1)); } @Test public void testApplyNotEmptyConstraintOnStringSchema() { Schema schema = new StringSchema(); boolean modified = ValidationAnnotationsUtils.applyNotEmptyConstraint(schema, null, null); assertTrue(modified); assertEquals(schema.getMinLength(), Integer.valueOf(1)); } @Test public void testApplyNotEmptyConstraintOnObjectSchema() { Schema schema = new ObjectSchema(); boolean modified = ValidationAnnotationsUtils.applyNotEmptyConstraint(schema, null, null); assertTrue(modified); assertEquals(schema.getMinProperties(), Integer.valueOf(1)); } @Test public void testApplyNotEmptyConstraintOnNumberSchema() { Schema schema = new NumberSchema(); boolean modified = ValidationAnnotationsUtils.applyNotEmptyConstraint(schema, null, null); assertFalse(modified); assertNull(schema.getMinProperties()); assertNull(schema.getMinLength()); assertNull(schema.getMinItems()); } @Test public void testApplyNotBlankConstraintOnStringSchema() { Schema schema = new StringSchema(); boolean modified = ValidationAnnotationsUtils.applyNotBlankConstraint(schema, null); assertTrue(modified); assertEquals(schema.getMinLength(), Integer.valueOf(1)); } @Test public void testApplyNotBlankConstraintOnNonStringSchema() { Schema schema = new NumberSchema(); boolean modified = ValidationAnnotationsUtils.applyNotBlankConstraint(schema, null); assertFalse(modified); assertNull(schema.getMinLength()); } @Test public void testApplyMinConstraintOnNumberSchema() { Schema schema = new NumberSchema(); Min minAnnotation = createMinAnnotation(10); boolean modified = ValidationAnnotationsUtils.applyMinConstraint(schema, minAnnotation); assertTrue(modified); assertEquals(schema.getMinimum(), new BigDecimal(10)); } @Test public void testApplyMinConstraintOnIntegerSchema() { Schema schema = new IntegerSchema(); Min minAnnotation = createMinAnnotation(5); boolean modified = ValidationAnnotationsUtils.applyMinConstraint(schema, minAnnotation); assertTrue(modified); assertEquals(schema.getMinimum(), new BigDecimal(5)); } @Test public void testApplyMinConstraintOnStringSchema() { Schema schema = new StringSchema(); Min minAnnotation = createMinAnnotation(10); boolean modified = ValidationAnnotationsUtils.applyMinConstraint(schema, minAnnotation); assertFalse(modified); assertNull(schema.getMinimum()); } @Test public void testApplyMaxConstraintOnNumberSchema() { Schema schema = new NumberSchema(); Max maxAnnotation = createMaxAnnotation(100); boolean modified = ValidationAnnotationsUtils.applyMaxConstraint(schema, maxAnnotation); assertTrue(modified); assertEquals(schema.getMaximum(), new BigDecimal(100)); } @Test public void testApplyMaxConstraintOnIntegerSchema() { Schema schema = new IntegerSchema(); Max maxAnnotation = createMaxAnnotation(50); boolean modified = ValidationAnnotationsUtils.applyMaxConstraint(schema, maxAnnotation); assertTrue(modified); assertEquals(schema.getMaximum(), new BigDecimal(50)); } @Test public void testApplyMaxConstraintOnStringSchema() { Schema schema = new StringSchema(); Max maxAnnotation = createMaxAnnotation(100); boolean modified = ValidationAnnotationsUtils.applyMaxConstraint(schema, maxAnnotation); assertFalse(modified); assertNull(schema.getMaximum()); } @Test public void testApplySizeConstraintOnNumberSchemaWithCustomValues() { Schema schema = new NumberSchema(); Size sizeAnnotation = createSizeAnnotation(10, 100); boolean modified = ValidationAnnotationsUtils.applySizeConstraint(schema, sizeAnnotation); assertTrue(modified); assertEquals(schema.getMinimum(), new BigDecimal(10)); assertEquals(schema.getMaximum(), new BigDecimal(100)); } @Test public void testApplySizeConstraintOnStringSchemaWithCustomValues() { Schema schema = new StringSchema(); Size sizeAnnotation = createSizeAnnotation(5, 50); boolean modified = ValidationAnnotationsUtils.applySizeConstraint(schema, sizeAnnotation); assertTrue(modified); assertEquals(schema.getMinLength(), Integer.valueOf(5)); assertEquals(schema.getMaxLength(), Integer.valueOf(50)); } @Test public void testApplySizeConstraintOnArraySchemaWithCustomValues() { Schema schema = new ArraySchema(); Size sizeAnnotation = createSizeAnnotation(1, 10); boolean modified = ValidationAnnotationsUtils.applySizeConstraint(schema, sizeAnnotation); assertTrue(modified); assertEquals(schema.getMinItems(), Integer.valueOf(1)); assertEquals(schema.getMaxItems(), Integer.valueOf(10)); } @Test public void testApplySizeConstraintOnObjectSchema() { Schema schema = new ObjectSchema(); Size sizeAnnotation = createSizeAnnotation(1, 10); boolean modified = ValidationAnnotationsUtils.applySizeConstraint(schema, sizeAnnotation); assertFalse(modified); } @Test public void testApplyDecimalMinConstraintOnNumberSchemaInclusive() { Schema schema = new NumberSchema(); DecimalMin minAnnotation = createDecimalMinAnnotation("10.5", true); boolean modified = ValidationAnnotationsUtils.applyDecimalMinConstraint(schema, minAnnotation); assertTrue(modified); assertEquals(schema.getMinimum(), new BigDecimal("10.5")); assertFalse(schema.getExclusiveMinimum()); } @Test public void testApplyDecimalMinConstraintOnNumberSchemaExclusive() { Schema schema = new NumberSchema(); DecimalMin minAnnotation = createDecimalMinAnnotation("10.5", false); boolean modified = ValidationAnnotationsUtils.applyDecimalMinConstraint(schema, minAnnotation); assertTrue(modified); assertEquals(schema.getMinimum(), new BigDecimal("10.5")); assertTrue(schema.getExclusiveMinimum()); } @Test public void testApplyDecimalMinConstraintOnStringSchema() { Schema schema = new StringSchema(); DecimalMin minAnnotation = createDecimalMinAnnotation("10.5", true); boolean modified = ValidationAnnotationsUtils.applyDecimalMinConstraint(schema, minAnnotation); assertFalse(modified); assertNull(schema.getMinimum()); } @Test public void testApplyDecimalMaxConstraintOnNumberSchemaInclusive() { Schema schema = new NumberSchema(); DecimalMax maxAnnotation = createDecimalMaxAnnotation("100.5", true); boolean modified = ValidationAnnotationsUtils.applyDecimalMaxConstraint(schema, maxAnnotation); assertTrue(modified); assertEquals(schema.getMaximum(), new BigDecimal("100.5")); assertFalse(schema.getExclusiveMaximum()); } @Test public void testApplyDecimalMaxConstraintOnNumberSchemaExclusive() { Schema schema = new NumberSchema(); DecimalMax maxAnnotation = createDecimalMaxAnnotation("100.5", false); boolean modified = ValidationAnnotationsUtils.applyDecimalMaxConstraint(schema, maxAnnotation); assertTrue(modified); assertEquals(schema.getMaximum(), new BigDecimal("100.5")); assertTrue(schema.getExclusiveMaximum()); } @Test public void testApplyDecimalMaxConstraintOnStringSchema() { Schema schema = new StringSchema(); DecimalMax maxAnnotation = createDecimalMaxAnnotation("100.5", true); boolean modified = ValidationAnnotationsUtils.applyDecimalMaxConstraint(schema, maxAnnotation); assertFalse(modified); assertNull(schema.getMaximum()); } @Test public void testApplyPatternConstraintOnStringSchema() { Schema schema = new StringSchema(); Pattern patternAnnotation = createPatternAnnotation("^[A-Z]+$"); boolean modified = ValidationAnnotationsUtils.applyPatternConstraint(schema, patternAnnotation); assertTrue(modified); assertEquals(schema.getPattern(), "^[A-Z]+$"); } @Test public void testApplyPatternConstraintOnArraySchemaWithStringItems() { Schema schema = new ArraySchema(); schema.setItems(new StringSchema()); Pattern patternAnnotation = createPatternAnnotation("^[0-9]+$"); boolean modified = ValidationAnnotationsUtils.applyPatternConstraint(schema, patternAnnotation); assertTrue(modified); assertNull(schema.getPattern()); assertEquals(schema.getItems().getPattern(), "^[0-9]+$"); } @Test public void testApplyPatternConstraintOnArraySchemaWithNumberItems() { Schema schema = new ArraySchema(); schema.setItems(new NumberSchema()); Pattern patternAnnotation = createPatternAnnotation("^[0-9]+$"); boolean modified = ValidationAnnotationsUtils.applyPatternConstraint(schema, patternAnnotation); assertFalse(modified); assertNull(schema.getItems().getPattern()); } @Test public void testApplyPatternConstraintOnNumberSchema() { Schema schema = new NumberSchema(); Pattern patternAnnotation = createPatternAnnotation("^[0-9]+$"); boolean modified = ValidationAnnotationsUtils.applyPatternConstraint(schema, patternAnnotation); assertFalse(modified); assertNull(schema.getPattern()); } @Test public void testApplyEmailConstraintOnStringSchema() { Schema schema = new StringSchema(); Email emailAnnotation = createEmailAnnotation(); boolean modified = ValidationAnnotationsUtils.applyEmailConstraint(schema, emailAnnotation); assertTrue(modified); assertEquals(schema.getFormat(), "email"); } @Test public void testApplyEmailConstraintOnArraySchemaWithStringItems() { Schema schema = new ArraySchema(); schema.setItems(new StringSchema()); Email emailAnnotation = createEmailAnnotation(); boolean modified = ValidationAnnotationsUtils.applyEmailConstraint(schema, emailAnnotation); assertTrue(modified); assertNull(schema.getFormat()); assertEquals(schema.getItems().getFormat(), "email"); } @Test public void testApplyEmailConstraintOnArraySchemaWithNumberItems() { Schema schema = new ArraySchema(); schema.setItems(new NumberSchema()); Email emailAnnotation = createEmailAnnotation(); boolean modified = ValidationAnnotationsUtils.applyEmailConstraint(schema, emailAnnotation); assertFalse(modified); assertNull(schema.getItems().getFormat()); } @Test public void testApplyEmailConstraintOnNumberSchema() { Schema schema = new NumberSchema(); Email emailAnnotation = createEmailAnnotation(); boolean modified = ValidationAnnotationsUtils.applyEmailConstraint(schema, emailAnnotation); assertFalse(modified); assertNull(schema.getFormat()); } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/reflection/ReflectionUtilsTest.java ================================================ package io.swagger.v3.core.util.reflection; import io.swagger.v3.core.util.ReflectionUtils; import io.swagger.v3.core.util.reflection.resources.Child; import io.swagger.v3.core.util.reflection.resources.IParent; import io.swagger.v3.core.util.reflection.resources.ObjectWithManyFields; import io.swagger.v3.core.util.reflection.resources.Parent; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import org.testng.annotations.Test; import javax.ws.rs.Path; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static java.lang.annotation.ElementType.PARAMETER; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; public class ReflectionUtilsTest { @Test public void typeFromStringTest() { assertEquals(ReflectionUtils.typeFromString("int"), (Type) Integer.class); assertEquals(ReflectionUtils.typeFromString("java.lang.String"), (Type) String.class); assertNull(ReflectionUtils.typeFromString("FakeType")); assertNull(ReflectionUtils.typeFromString(null)); } @Test public void isOverriddenMethodTest() throws NoSuchMethodException { for (Method method : Child.class.getMethods()) { if ("parametrizedMethod1".equals(method.getName())) { final boolean result = ReflectionUtils.isOverriddenMethod(method, Child.class); final Class first = method.getParameterTypes()[0]; if (Number.class.equals(first)) { assertTrue(result); } else if (Integer.class.equals(first)) { assertFalse(result); } } else if ("parametrizedMethod3".equals(method.getName())) { assertFalse(ReflectionUtils.isOverriddenMethod(method, Child.class)); } } for (Method method : Object.class.getMethods()) { if ("equals".equals(method.getName())) { assertFalse(ReflectionUtils.isOverriddenMethod(method, Object.class)); } } for (Method method : IParent.class.getMethods()) { if ("parametrizedMethod5".equals(method.getName())) { assertFalse(ReflectionUtils.isOverriddenMethod(method, IParent.class)); } else if ("parametrizedMethod2".equals(method.getName())) { assertFalse(ReflectionUtils.isOverriddenMethod(method, IParent.class)); } else { fail("Method not expected"); } } } @Test public void getOverriddenMethodTest() throws NoSuchMethodException { final Method method1 = ReflectionUtils.getOverriddenMethod( Child.class.getMethod("parametrizedMethod1", Integer.class)); assertNotNull(method1); assertEquals(method1.getParameterTypes()[0], Number.class); final Method method2 = ReflectionUtils.getOverriddenMethod( Child.class.getMethod("parametrizedMethod2", Long.class)); assertNotNull(method2); assertEquals(method2.getParameterTypes()[0], Number.class); final Method method3 = ReflectionUtils.getOverriddenMethod( Child.class.getMethod("parametrizedMethod3", Long.class)); assertNull(method3); assertNull(ReflectionUtils.getOverriddenMethod(Object.class.getMethod("equals", Object.class))); } @Test public void findMethodTest() throws NoSuchMethodException { final Method methodToFind1 = Child.class.getMethod("parametrizedMethod1", Integer.class); final Method method1 = ReflectionUtils.findMethod(methodToFind1, Parent.class); assertNotNull(method1); assertEquals(method1.getParameterTypes()[0], Number.class); final Method methodToFind2 = Child.class.getMethod("parametrizedMethod4", Long.class); final Method method2 = ReflectionUtils.findMethod(methodToFind2, Parent.class); assertNull(method2); } @Test public void isInjectTest() throws NoSuchMethodException { final Method injectableMethod = Child.class.getMethod("injectableMethod"); assertTrue(ReflectionUtils.isInject(Arrays.asList(injectableMethod.getDeclaredAnnotations()))); final Method methodToFind = Child.class.getMethod("parametrizedMethod1", Integer.class); assertFalse(ReflectionUtils.isInject(Arrays.asList(methodToFind.getDeclaredAnnotations()))); } @Test public void isConstructorCompatibleTest() throws NoSuchMethodException { assertFalse(ReflectionUtils.isConstructorCompatible(Child.class.getDeclaredConstructor())); assertTrue(ReflectionUtils.isConstructorCompatible(Child.class.getDeclaredConstructor(String.class))); } @Test public void getAnnotationTest() throws NoSuchMethodException { final Method method = Child.class.getMethod("annotationHolder"); assertNotNull(ReflectionUtils.getAnnotation(method, Schema.class)); assertNull(ReflectionUtils.getAnnotation(method, ApiResponse.class)); } @Test public void isVoidTest() { assertTrue(ReflectionUtils.isVoid(Void.class)); assertTrue(ReflectionUtils.isVoid(Void.TYPE)); assertFalse(ReflectionUtils.isVoid(String.class)); } @Test public void testDerivedAnnotation() { final Path annotation = ReflectionUtils.getAnnotation(Child.class, javax.ws.rs.Path.class); assertNotNull(annotation); assertEquals(annotation.value(), "parentInterfacePath"); } @Test public void getDeclaredFieldsFromInterfaceTest() throws NoSuchMethodException { final Class cls = IParent.class; assertEquals(Collections.emptyList(), ReflectionUtils.getDeclaredFields(cls)); } @Test public void declaredFieldsShouldBeSorted() { final Class cls = ObjectWithManyFields.class; final List declaredFields = ReflectionUtils.getDeclaredFields(cls); assertEquals(declaredFields.size(), 4); assertEquals(Arrays.asList("a", "b", "c", "d"), declaredFields.stream().map(Field::getName).collect(Collectors.toList())); } @Test public void testFindMethodForNullClass() throws Exception { Method method = ReflectionUtilsTest.class.getMethod("testFindMethodForNullClass", (Class[]) null); assertNull(ReflectionUtils.findMethod(method, null)); } @Test public void getRepeatableAnnotationsArrayTest() { Tag[] annotations = ReflectionUtils.getRepeatableAnnotationsArray(InheritingClass.class, Tag.class); assertNotNull(annotations); assertEquals(annotations.length, 1); assertNotNull(annotations[0]); assertEquals(annotations[0].name(), "inherited tag"); } @Test public void getParameterAnnotationsTest() throws NoSuchMethodException { Method method = SecondLevelSubClass.class.getMethod("method", String.class); Annotation[][] parameterAnnotations = ReflectionUtils.getParameterAnnotations(method); assertEquals(parameterAnnotations.length, 1); assertEquals(parameterAnnotations[0].length, 1); assertTrue(parameterAnnotations[0][0] instanceof AnnotationInterface); assertEquals(((AnnotationInterface)parameterAnnotations[0][0]).value(), "level1"); } @Test public void getParameterAnnotationsForOverriddenAnnotationTest() throws NoSuchMethodException { Method method = ThirdLevelSubClass.class.getMethod("method", String.class); Annotation[][] parameterAnnotations = ReflectionUtils.getParameterAnnotations(method); assertEquals(parameterAnnotations.length, 1); assertEquals(parameterAnnotations[0].length, 1); assertTrue(parameterAnnotations[0][0] instanceof AnnotationInterface); assertEquals(((AnnotationInterface)parameterAnnotations[0][0]).value(), "level4"); } @Tag(name = "inherited tag") private interface AnnotatedInterface {} private class InheritingClass implements AnnotatedInterface {} @Target({PARAMETER}) @Retention(RetentionPolicy.RUNTIME) private @interface AnnotationInterface { String value(); } private static class BaseClass { public void method(@AnnotationInterface("level1") String example) {} } private static class FirstLevelSubClass extends BaseClass { @Override public void method(String example){} } private static class SecondLevelSubClass extends FirstLevelSubClass { @Override public void method(String example){} } private static class ThirdLevelSubClass extends SecondLevelSubClass { @Override public void method(@AnnotationInterface("level4") String example){} } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/reflection/resources/Child.java ================================================ package io.swagger.v3.core.util.reflection.resources; import javax.inject.Inject; public class Child extends Parent implements IParent { protected Child() { } public Child(String arg) { } @Override public Integer parametrizedMethod1(Integer arg) { return null; } @Override public String parametrizedMethod2(Long arg) { return null; } public Integer parametrizedMethod3(Long arg) { return null; } public Integer parametrizedMethod4(Long arg) { return null; } @Override public String parametrizedMethod5(Long arg) { return null; } @Override public void annotationHolder() { } @Deprecated @Inject public void injectableMethod() { } @IndirectAnnotation public void indirectAnnotationMethod() { } } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/reflection/resources/IGrandparent.java ================================================ package io.swagger.v3.core.util.reflection.resources; public interface IGrandparent { String parametrizedMethod5(T arg); } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/reflection/resources/IParent.java ================================================ package io.swagger.v3.core.util.reflection.resources; import javax.ws.rs.Path; @Path("parentInterfacePath") @IndirectAnnotation public interface IParent extends IGrandparent { public String parametrizedMethod2(T arg); @Override String parametrizedMethod5(T arg); } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/reflection/resources/IndirectAnnotation.java ================================================ package io.swagger.v3.core.util.reflection.resources; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @interface IndirectAnnotation { } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/reflection/resources/ObjectWithManyFields.java ================================================ package io.swagger.v3.core.util.reflection.resources; public class ObjectWithManyFields { public String a; public boolean d; public Integer c; public Object b; } ================================================ FILE: modules/swagger-core/src/test/java/io/swagger/v3/core/util/reflection/resources/Parent.java ================================================ package io.swagger.v3.core.util.reflection.resources; import io.swagger.v3.oas.annotations.media.Schema; @IndirectAnnotation public class Parent { public T parametrizedMethod1(T arg) { return null; } public Long parametrizedMethod3(Integer arg) { return null; } public Integer parametrizedMethod4(Integer arg) { return null; } public Integer parametrizedMethod4(Integer arg1, Integer arg2) { return null; } @Schema(title = "test") public void annotationHolder() { } @Override public boolean equals(Object obj) { return super.equals(obj); } } ================================================ FILE: modules/swagger-core/src/test/resources/AbstractBaseModelWithoutFields.json ================================================ { "AbstractBaseModelWithoutFields": { "type": "object", "description": "I am an Abstract Base Model without any declared fields and with Sub-Types" }, "Thing3": { "type": "object", "description": "Thing3", "allOf": [ { "$ref": "#/components/schemas/AbstractBaseModelWithoutFields" }, { "type": "object", "properties": { "a": { "type": "string", "description": "Additional field a" }, "x": { "type": "integer", "format": "int32", "description": "Additional field x" } } } ] } } ================================================ FILE: modules/swagger-core/src/test/resources/Animal.json ================================================ { "Animal": { "type": "object", "properties": { "name": { "type": "string" }, "type": { "type": "string" } }, "discriminator" : { "propertyName" : "type" } }, "Human": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/Animal" }, { "type": "object", "properties": { "firstName": { "type": "string" }, "lastName": { "type": "string" } } } ] }, "Pet": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/Animal" }, { "type": "object", "properties": { "type": { "type": "string", "description": "The pet type" }, "name": { "type": "string", "description": "The name of the pet" }, "isDomestic": { "type": "boolean" } } } ], "required": [ "isDomestic", "name", "type" ] } } ================================================ FILE: modules/swagger-core/src/test/resources/AnimalClass.json ================================================ { "AnimalClass": { "type": "object", "properties": { "name": { "type": "string" }, "type": { "type": "string" } }, "discriminator" : { "propertyName" : "type" } }, "HumanClass": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/AnimalClass" }, { "type": "object", "properties": { "firstName": { "type": "string" }, "lastName": { "type": "string" } } } ] }, "PetClass": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/AnimalClass" }, { "type": "object", "properties": { "type": { "type": "string", "description": "The pet type" }, "name": { "type": "string", "description": "The name of the pet" }, "isDomestic": { "type": "boolean" } } } ], "required": [ "isDomestic", "name", "type" ] } } ================================================ FILE: modules/swagger-core/src/test/resources/AnimalWithSchemaSubtypes.json ================================================ { "AnimalWithSchemaSubtypes": { "type": "object", "properties": { "name": { "type": "string" }, "type": { "type": "string" } }, "discriminator" : { "propertyName" : "type" } }, "HumanWithSchemaSubtypes": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/AnimalWithSchemaSubtypes" }, { "type": "object", "properties": { "firstName": { "type": "string" }, "lastName": { "type": "string" } } } ] }, "PetWithSchemaSubtypes": { "type": "object", "allOf": [ { "$ref": "#/components/schemas/AnimalWithSchemaSubtypes" }, { "type": "object", "properties": { "type": { "type": "string", "description": "The pet type" }, "name": { "type": "string", "description": "The name of the pet" }, "isDomestic": { "type": "boolean" } } } ], "required": [ "isDomestic", "name", "type" ] } } ================================================ FILE: modules/swagger-core/src/test/resources/Cat.json ================================================ { "Cat": { "required": [ "isDomestic", "name", "type" ], "type": "object", "properties": { "clawCount": { "type": "integer", "format": "int32" }, "type": { "type": "string", "description": "The pet type" }, "name": { "type": "string", "description": "The name of the pet" }, "isDomestic": { "type": "boolean" } } } } ================================================ FILE: modules/swagger-core/src/test/resources/GuavaTestModel.json ================================================ { "GuavaModel": { "type": "object", "properties": { "name": { "type": "string" } } } } ================================================ FILE: modules/swagger-core/src/test/resources/Human.json ================================================ { "Human": { "type": "object", "properties": { "name": { "type": "string" }, "type": { "type": "string" }, "firstName": { "type": "string" }, "lastName": { "type": "string" } } } } ================================================ FILE: modules/swagger-core/src/test/resources/JodaDateTimeModel.json ================================================ { "JodaDateTimeModel": { "type": "object", "properties": { "createdAt": { "type": "string", "format": "date-time" } } } } ================================================ FILE: modules/swagger-core/src/test/resources/ModelWithFieldWithSubTypes.json ================================================ { "AbstractBaseModelWithSubTypes": { "type": "object", "discriminator" : { "propertyName" : "_type" }, "properties": { "_type": { "type": "string", "description": "This value is used as a discriminator for serialization" }, "a": { "type": "string", "description": "An arbitrary field" }, "b": { "type": "string", "description": "An arbitrary field" } }, "description": "I am an Abstract Base Model with Sub-Types" }, "ModelWithFieldWithSubTypes": { "type": "object", "properties": { "z": { "$ref": "#/components/schemas/AbstractBaseModelWithSubTypes" } }, "description": "Class that has a field that is the AbstractBaseModelWithSubTypes" }, "Thing1": { "type": "object", "description": "Shake hands with Thing1", "allOf": [ { "$ref": "#/components/schemas/AbstractBaseModelWithSubTypes" }, { "type": "object", "properties": { "a": { "type": "string", "description": "Override the abstract a" }, "x": { "type": "integer", "format": "int32", "description": "Thing1 has an additional field" } } } ] }, "Thing2": { "type": "object", "description": "and Thing2", "allOf": [ { "$ref": "#/components/schemas/AbstractBaseModelWithSubTypes" }, { "type": "object", "properties": { "a": { "type": "string", "description": "Override the abstract a" }, "s": { "type": "string", "description": "Thing2 has an additional field" } } } ] } } ================================================ FILE: modules/swagger-core/src/test/resources/ModelWithFormattedStrings.json ================================================ { "type": "object", "properties": { "uuid": { "type": "string", "format": "uuid" }, "uri": { "type": "string", "format": "uri" }, "url": { "type": "string", "format": "url" }, "date": { "type": "string", "format": "date-time" }, "aByte": { "type": "string", "format": "byte" }, "aByteObject": { "type": "string", "format": "byte" } } } ================================================ FILE: modules/swagger-core/src/test/resources/ModelWithSecurityRequirements.json ================================================ { "openapi": "3.0.1", "info": { "title": "Swagger Petstore", "contact": { "name": "Swagger API Team", "url": "http://swagger.io", "email": "foo@bar.baz" }, "version": "1.0.0" }, "servers": [ { "url": "http://petstore.swagger.io" } ], "paths": { "/pets": { "get": { "tags": [ "Pet Operations" ], "summary": "finds pets in the system", "description": "a longer description", "operationId": "get pet by id", "parameters": [ { "name": "tags", "in": "query", "description": "tags to filter by", "required": false, "schema": { "type": "string" } }, { "name": "petId", "in": "path", "description": "pet to fetch", "required": true, "schema": { "type": "integer", "format": "int64" } } ], "responses": { "200": { "description": "pets returned", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/Person" } } } }, "default": { "description": "error response", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/Error" } } } } }, "security": [ { "internal_oauth2": ["user:email"] }, { "api_key": [] } ] } } }, "components": { "schemas": { "Person": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "firstName": { "type": "string" }, "address": { "$ref": "#/components/schemas/Address" }, "properties": { "type": "object", "additionalProperties": { "type": "string" } }, "birthDate": { "type": "string", "format": "date-time" }, "float": { "type": "number", "format": "float" }, "double": { "type": "number", "format": "double" } } } }, "securitySchemes": { "githubAccessCode": { "flows": { "authorizationCode": { "scopes": { "user:email": "Grants read access to a user’s email addresses." } } } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/Person.json ================================================ { "Person": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "firstName": { "type": "string" }, "address": { "$ref": "#/components/schemas/Address" }, "properties": { "type": "object", "additionalProperties": { "type": "string" } }, "birthDate": { "type": "string", "format": "date-time" }, "float": { "type": "number", "format": "float" }, "double": { "type": "number", "format": "double" } } } } ================================================ FILE: modules/swagger-core/src/test/resources/Pet.json ================================================ { "Pet": { "required": [ "isDomestic", "name", "type" ], "type": "object", "properties": { "type": { "type": "string", "description": "The pet type" }, "name": { "type": "string", "description": "The name of the pet" }, "isDomestic": { "type": "boolean" } } } } ================================================ FILE: modules/swagger-core/src/test/resources/comprehensiveOAS31/comprehensive-openapi.yaml ================================================ # Comprehensive OpenAPI 3.1 and JSON Schema 2020/12 Example # This file demonstrates a comprehensive OpenAPI 3.1 document with JSON Schema 2020/12 features # It includes all keywords defined in both specifications and uses both internal and external references openapi: 3.1.0 jsonSchemaDialect: https://json-schema.org/draft/2020-12/schema # Basic information about the API info: title: Comprehensive Pet Store API version: 1.0.0 summary: A comprehensive example of an OpenAPI 3.1 document with JSON Schema 2020/12 features description: | This is a comprehensive example of an OpenAPI 3.1 document that includes all keywords defined in both OpenAPI 3.1 and JSON Schema 2020/12 specifications. It demonstrates the use of both internal and external references, as well as seldom used constructs like $schema, $id, and $dynamicAnchor. The API allows you to manage pets, users, and orders in a pet store. termsOfService: https://example.com/terms/ contact: name: API Support url: https://example.com/support email: support@example.com license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html identifier: Apache-2.0 # Server information servers: - url: https://api.example.com/v1 description: Production server - url: https://staging-api.example.com/v1 description: Staging server variables: port: enum: - '8443' - '443' default: '443' basePath: default: v1 - url: https://dev-api.example.com/v1 description: Development server - url: http://localhost:{port}/{basePath} description: Local development server variables: port: enum: - '8080' - '8081' default: '8080' basePath: default: v1 # External documentation externalDocs: description: Find more info here url: https://example.com/docs # Tags for API documentation control and organization tags: - name: pets description: Pet operations externalDocs: description: Find more info about pets url: https://example.com/docs/pets - name: users description: User operations externalDocs: description: Find more info about users url: https://example.com/docs/users - name: orders description: Order operations externalDocs: description: Find more info about orders url: https://example.com/docs/orders # Security schemes security: - petstore_auth: - read:pets - write:pets - user_auth: - read:users - write:users - order_auth: - read:orders - write:orders - api_key: [] # Paths paths: # Pet paths /pets: $ref: "./paths/pet-paths.yaml#/~1pets" /pets/{petId}: $ref: "./paths/pet-paths.yaml#/~1pets~1{petId}" /pets/findByStatus: $ref: "./paths/pet-paths.yaml#/~1pets~1findByStatus" /pets/findByTags: $ref: "./paths/pet-paths.yaml#/~1pets~1findByTags" /pets/{petId}/uploadImage: $ref: "./paths/pet-paths.yaml#/~1pets~1{petId}~1uploadImage" # User paths /users: $ref: "./paths/user-paths.yaml#/~1users" /users/{userId}: $ref: "./paths/user-paths.yaml#/~1users~1{userId}" /users/login: $ref: "./paths/user-paths.yaml#/~1users~1login" /users/logout: $ref: "./paths/user-paths.yaml#/~1users~1logout" /users/{userId}/preferences: $ref: "./paths/user-paths.yaml#/~1users~1{userId}~1preferences" # Order paths /orders: $ref: "./paths/order-paths.yaml#/~1orders" /orders/{orderId}: $ref: "./paths/order-paths.yaml#/~1orders~1{orderId}" /orders/{orderId}/status: $ref: "./paths/order-paths.yaml#/~1orders~1{orderId}~1status" /orders/{orderId}/invoice: $ref: "./paths/order-paths.yaml#/~1orders~1{orderId}~1invoice" /orders/{orderId}/shipment: $ref: "./paths/order-paths.yaml#/~1orders~1{orderId}~1shipment" # Additional path with inline definition /health: get: summary: Health check description: Returns the health status of the API operationId: healthCheck tags: - system responses: '200': description: Health check response content: application/json: schema: type: object properties: status: type: string enum: [ok, degraded, down] version: type: string timestamp: type: string format: date-time required: - status - version - timestamp examples: healthy: summary: Healthy response value: status: ok version: 1.0.0 timestamp: "2023-01-01T12:00:00Z" degraded: summary: Degraded response value: status: degraded version: 1.0.0 timestamp: "2023-01-01T12:00:00Z" security: [] # Webhooks webhooks: newPet: post: summary: New pet webhook description: Webhook for when a new pet is created operationId: newPetWebhook tags: - pets - webhooks requestBody: description: Information about the new pet required: true content: application/json: schema: $ref: "./schemas/pet-schemas.yaml#/Pet" responses: '200': description: Webhook processed successfully '400': description: Bad request content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" updatedPet: post: summary: Updated pet webhook description: Webhook for when a pet is updated operationId: updatedPetWebhook tags: - pets - webhooks requestBody: description: Information about the updated pet required: true content: application/json: schema: $ref: "./schemas/pet-schemas.yaml#/Pet" responses: '200': description: Webhook processed successfully '400': description: Bad request content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" newOrder: post: summary: New order webhook description: Webhook for when a new order is created operationId: newOrderWebhook tags: - orders - webhooks requestBody: description: Information about the new order required: true content: application/json: schema: $ref: "./schemas/order-schemas.yaml#/Order" responses: '200': description: Webhook processed successfully '400': description: Bad request content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" # Components components: # Schemas schemas: # Common schemas Error: $ref: "./schemas/common-schemas.yaml#/Error" Identifiable: $ref: "./schemas/common-schemas.yaml#/Identifiable" ExtendedSchema: $ref: "./schemas/common-schemas.yaml#/ExtendedSchema" CommentedSchema: $ref: "./schemas/common-schemas.yaml#/CommentedSchema" SchemaWithDefs: $ref: "./schemas/common-schemas.yaml#/SchemaWithDefs" ValidationSchema: $ref: "./schemas/common-schemas.yaml#/ValidationSchema" ApplicatorSchema: $ref: "./schemas/common-schemas.yaml#/ApplicatorSchema" # Pet schemas Pet: $ref: "./schemas/pet-schemas.yaml#/Pet" Category: $ref: "./schemas/pet-schemas.yaml#/Category" Tag: $ref: "./schemas/pet-schemas.yaml#/Tag" Dog: $ref: "./schemas/pet-schemas.yaml#/Dog" Cat: $ref: "./schemas/pet-schemas.yaml#/Cat" Bird: $ref: "./schemas/pet-schemas.yaml#/Bird" Pets: $ref: "./schemas/pet-schemas.yaml#/Pets" PetWithValidation: $ref: "./schemas/pet-schemas.yaml#/PetWithValidation" PetWithConditional: $ref: "./schemas/pet-schemas.yaml#/PetWithConditional" # User schemas User: $ref: "./schemas/user-schemas.yaml#/User" Address: $ref: "./schemas/user-schemas.yaml#/Address" UserArray: $ref: "./schemas/user-schemas.yaml#/UserArray" UserWithRoles: $ref: "./schemas/user-schemas.yaml#/UserWithRoles" Role: $ref: "./schemas/user-schemas.yaml#/Role" Permission: $ref: "./schemas/user-schemas.yaml#/Permission" UserCredentials: $ref: "./schemas/user-schemas.yaml#/UserCredentials" UserPreferences: $ref: "./schemas/user-schemas.yaml#/UserPreferences" UserWithPreferences: $ref: "./schemas/user-schemas.yaml#/UserWithPreferences" # Order schemas Order: $ref: "./schemas/order-schemas.yaml#/Order" OrderItem: $ref: "./schemas/order-schemas.yaml#/OrderItem" OrderWithItems: $ref: "./schemas/order-schemas.yaml#/OrderWithItems" OrderStatus: $ref: "./schemas/order-schemas.yaml#/OrderStatus" OrderArray: $ref: "./schemas/order-schemas.yaml#/OrderArray" OrderSummary: $ref: "./schemas/order-schemas.yaml#/OrderSummary" Invoice: $ref: "./schemas/order-schemas.yaml#/Invoice" Payment: $ref: "./schemas/order-schemas.yaml#/Payment" Shipment: $ref: "./schemas/order-schemas.yaml#/Shipment" # External JSON Schema reference JsonSchema: $ref: "./schemas/json-schema.yaml" # Additional inline schemas with JSON Schema 2020/12 features BooleanSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/BooleanSchema" $anchor: "BooleanSchema" title: "Boolean Schema" description: "A schema that is just a boolean value" type: boolean NullSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/NullSchema" $anchor: "NullSchema" title: "Null Schema" description: "A schema that is just a null value" type: "null" MultiTypeSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/MultiTypeSchema" $anchor: "MultiTypeSchema" title: "Multi-Type Schema" description: "A schema that accepts multiple types" type: [string, number, boolean, "null"] RecursiveSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/RecursiveSchema" $anchor: "RecursiveSchema" title: "Recursive Schema" description: "A schema that references itself" type: object properties: id: type: string name: type: string children: type: array items: $ref: "#/components/schemas/RecursiveSchema" required: - id - name UnevaluatedSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/UnevaluatedSchema" $anchor: "UnevaluatedSchema" title: "Unevaluated Schema" description: "A schema that uses unevaluatedProperties and unevaluatedItems" type: object properties: id: type: string name: type: string unevaluatedProperties: false allOf: - properties: age: type: integer unevaluatedProperties: false ContentSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/ContentSchema" $anchor: "ContentSchema" title: "Content Schema" description: "A schema that uses contentEncoding and contentMediaType" type: string contentEncoding: base64 contentMediaType: image/png DynamicRefSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/DynamicRefSchema" $anchor: "DynamicRefSchema" title: "Dynamic Ref Schema" description: "A schema that uses $dynamicRef" type: object properties: entity: $dynamicRef: "#Identifiable" required: - entity # Path items pathItems: petPath: summary: Pet path item description: Path item for pet operations get: summary: Get pet description: Returns a pet operationId: getPet tags: - pets parameters: - name: petId in: path description: ID of pet to return required: true schema: type: integer format: int64 minimum: 1 responses: '200': description: Successful operation content: application/json: schema: $ref: "./schemas/pet-schemas.yaml#/Pet" '400': description: Invalid ID supplied content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" '404': description: Pet not found content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" security: - petstore_auth: - read:pets - api_key: [] userPath: summary: User path item description: Path item for user operations get: summary: Get user description: Returns a user operationId: getUser tags: - users parameters: - name: userId in: path description: ID of user to return required: true schema: type: integer format: int64 minimum: 1 responses: '200': description: Successful operation content: application/json: schema: $ref: "./schemas/user-schemas.yaml#/User" '400': description: Invalid ID supplied content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" '404': description: User not found content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" security: - user_auth: - read:users - api_key: [] orderPath: summary: Order path item description: Path item for order operations get: summary: Get order description: Returns an order operationId: getOrder tags: - orders parameters: - name: orderId in: path description: ID of order to return required: true schema: type: integer format: int64 minimum: 1 responses: '200': description: Successful operation content: application/json: schema: $ref: "./schemas/order-schemas.yaml#/Order" '400': description: Invalid ID supplied content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" security: - order_auth: - read:orders - api_key: [] # Parameters parameters: limitParam: name: limit in: query description: Maximum number of items to return required: false schema: type: integer format: int32 minimum: 1 maximum: 100 default: 20 offsetParam: name: offset in: query description: Offset for pagination required: false schema: type: integer format: int32 minimum: 0 default: 0 petIdParam: name: petId in: path description: ID of pet to return required: true schema: type: integer format: int64 minimum: 1 userIdParam: name: userId in: path description: ID of user to return required: true schema: type: integer format: int64 minimum: 1 orderIdParam: name: orderId in: path description: ID of order to return required: true schema: type: integer format: int64 minimum: 1 # Request bodies requestBodies: petRequestBody: description: Pet object that needs to be added to the store required: true content: application/json: schema: $ref: "./schemas/pet-schemas.yaml#/Pet" userRequestBody: description: User object that needs to be added to the system required: true content: application/json: schema: $ref: "./schemas/user-schemas.yaml#/User" orderRequestBody: description: Order object that needs to be added to the store required: true content: application/json: schema: $ref: "./schemas/order-schemas.yaml#/Order" # Responses responses: notFound: description: The specified resource was not found content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" badRequest: description: The request was invalid content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" unauthorized: description: Authentication information is missing or invalid headers: WWW-Authenticate: schema: type: string content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" forbidden: description: The server understood the request but refuses to authorize it content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" serverError: description: An unexpected error occurred content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" # Headers headers: X-Rate-Limit: description: Calls per hour allowed by the user schema: type: integer format: int32 X-Expires-After: description: Date in UTC when token expires schema: type: string format: date-time X-Total-Count: description: Total number of items schema: type: integer format: int32 minimum: 0 # Security schemes securitySchemes: petstore_auth: type: oauth2 description: OAuth2 authentication for pet operations flows: implicit: authorizationUrl: https://example.com/oauth/authorize scopes: read:pets: read your pets write:pets: modify pets in your account user_auth: type: oauth2 description: OAuth2 authentication for user operations flows: implicit: authorizationUrl: https://example.com/oauth/authorize scopes: read:users: read user information write:users: modify user information order_auth: type: oauth2 description: OAuth2 authentication for order operations flows: implicit: authorizationUrl: https://example.com/oauth/authorize scopes: read:orders: read your orders write:orders: modify orders in your account api_key: type: apiKey description: API key authentication name: api_key in: header # Examples examples: pet: summary: Example of a pet value: id: 1 name: Fluffy status: available user: summary: Example of a user value: id: 1 username: john_doe email: john@example.com order: summary: Example of an order value: id: 1 petId: 1 quantity: 1 shipDate: "2023-01-01T12:00:00Z" status: placed complete: false # Links links: getPetById: operationId: getPetById parameters: petId: $response.body#/id description: The `id` value returned in the response can be used as the `petId` parameter in `GET /pets/{petId}` getUserById: operationId: getUserById parameters: userId: $response.body#/id description: The `id` value returned in the response can be used as the `userId` parameter in `GET /users/{userId}` getOrderById: operationId: getOrderById parameters: orderId: $response.body#/id description: The `id` value returned in the response can be used as the `orderId` parameter in `GET /orders/{orderId}` # Callbacks callbacks: petStatusChanged: '{$request.body#/status}': post: summary: Pet status changed callback description: Callback for when a pet's status changes operationId: petStatusChangedCallback requestBody: description: Pet status change information required: true content: application/json: schema: type: object properties: petId: type: integer format: int64 oldStatus: type: string newStatus: type: string required: - petId - oldStatus - newStatus responses: '200': description: Callback processed successfully '400': description: Bad request content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" orderStatusChanged: '{$request.body#/status}': post: summary: Order status changed callback description: Callback for when an order's status changes operationId: orderStatusChangedCallback requestBody: description: Order status change information required: true content: application/json: schema: type: object properties: orderId: type: integer format: int64 oldStatus: type: string newStatus: type: string required: - orderId - oldStatus - newStatus responses: '200': description: Callback processed successfully '400': description: Bad request content: application/json: schema: $ref: "./schemas/common-schemas.yaml#/Error" # Extensions x-api-version: 1.0.0 x-generated-at: "2023-01-01T12:00:00Z" x-generated-by: "OpenAPI Generator" x-logo: url: "https://example.com/logo.png" backgroundColor: "#FFFFFF" altText: "Example API Logo" ================================================ FILE: modules/swagger-core/src/test/resources/comprehensiveOAS31/paths/order-paths.yaml ================================================ # Order Paths for OpenAPI 3.1 # This file contains order-related paths referenced by the root file # Path for /orders /orders: get: summary: List all orders description: Returns all orders from the system that the user has access to operationId: listOrders tags: - orders parameters: - name: limit in: query description: Maximum number of orders to return required: false schema: type: integer format: int32 minimum: 1 maximum: 100 default: 20 - name: offset in: query description: Offset for pagination required: false schema: type: integer format: int32 minimum: 0 default: 0 - name: status in: query description: Status values that need to be considered for filter required: false schema: type: string enum: [placed, approved, delivered, cancelled] - name: userId in: query description: User ID to filter by required: false schema: type: integer format: int64 minimum: 1 - name: sort in: query description: Sort order required: false schema: type: string enum: [id, status, createdAt] default: createdAt responses: '200': description: A paged array of orders headers: x-next: description: A link to the next page of responses schema: type: string format: uri x-total-count: description: Total number of orders schema: type: integer format: int32 minimum: 0 content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/OrderArray" examples: orders: summary: Example of orders value: - id: 1 petId: 1 quantity: 1 shipDate: "2023-01-01T12:00:00Z" status: placed complete: false - id: 2 petId: 2 quantity: 2 shipDate: "2023-01-02T12:00:00Z" status: approved complete: false '400': description: Bad request content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '401': description: Unauthorized content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '403': description: Forbidden content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - read:orders post: summary: Create an order description: Creates a new order in the store operationId: createOrder tags: - orders requestBody: description: Order to add to the store required: true content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Order" examples: order: summary: Example of an order value: id: 0 petId: 1 quantity: 1 shipDate: "2023-01-01T12:00:00Z" status: placed complete: false responses: '201': description: Order created headers: Location: description: URL of the newly created order schema: type: string format: uri content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Order" '400': description: Bad request content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '401': description: Unauthorized content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '403': description: Forbidden content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - write:orders # Path for /orders/{orderId} /orders/{orderId}: parameters: - name: orderId in: path description: ID of order to return required: true schema: type: integer format: int64 minimum: 1 get: summary: Find order by ID description: Returns a single order operationId: getOrderById tags: - orders responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Order" examples: order: summary: Example of an order value: id: 1 petId: 1 quantity: 1 shipDate: "2023-01-01T12:00:00Z" status: placed complete: false '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - read:orders - api_key: [] put: summary: Update an existing order description: Updates an order in the store operationId: updateOrder tags: - orders requestBody: description: Order to update required: true content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Order" examples: order: summary: Example of an order value: id: 1 petId: 1 quantity: 1 shipDate: "2023-01-01T12:00:00Z" status: approved complete: false responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Order" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '405': description: Validation exception content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - write:orders delete: summary: Deletes an order description: Deletes an order from the store operationId: deleteOrder tags: - orders responses: '204': description: Order deleted '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - write:orders # Path for /orders/{orderId}/status /orders/{orderId}/status: parameters: - name: orderId in: path description: ID of order to update status required: true schema: type: integer format: int64 minimum: 1 get: summary: Get order status description: Returns the status of an order operationId: getOrderStatus tags: - orders responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/OrderStatus" examples: status: summary: Example of order status value: id: 1 status: placed timestamp: "2023-01-01T12:00:00Z" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - read:orders put: summary: Update order status description: Updates the status of an order operationId: updateOrderStatus tags: - orders requestBody: description: Status to update required: true content: application/json: schema: type: object required: - status properties: status: type: string description: Order status enum: [placed, approved, delivered, cancelled] notes: type: string description: Status notes maxLength: 500 examples: status: summary: Example of status update value: status: approved notes: "Approved by manager" responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/OrderStatus" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - write:orders # Path for /orders/{orderId}/invoice /orders/{orderId}/invoice: parameters: - name: orderId in: path description: ID of order to get invoice for required: true schema: type: integer format: int64 minimum: 1 get: summary: Get order invoice description: Returns the invoice for an order operationId: getOrderInvoice tags: - orders responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Invoice" examples: invoice: summary: Example of an invoice value: id: 1 orderId: 1 amount: 100.0 tax: 10.0 shipping: 5.0 total: 115.0 status: pending createdAt: "2023-01-01T12:00:00Z" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - read:orders post: summary: Create order invoice description: Creates an invoice for an order operationId: createOrderInvoice tags: - orders requestBody: description: Invoice to create required: true content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Invoice" examples: invoice: summary: Example of an invoice value: id: 0 orderId: 1 amount: 100.0 tax: 10.0 shipping: 5.0 total: 115.0 status: pending responses: '201': description: Invoice created headers: Location: description: URL of the newly created invoice schema: type: string format: uri content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Invoice" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - write:orders # Path for /orders/{orderId}/shipment /orders/{orderId}/shipment: parameters: - name: orderId in: path description: ID of order to get shipment for required: true schema: type: integer format: int64 minimum: 1 get: summary: Get order shipment description: Returns the shipment for an order operationId: getOrderShipment tags: - orders responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Shipment" examples: shipment: summary: Example of a shipment value: id: 1 orderId: 1 status: shipped trackingNumber: "1Z999AA10123456784" carrier: ups estimatedDelivery: "2023-01-05" createdAt: "2023-01-01T12:00:00Z" shippedAt: "2023-01-02T12:00:00Z" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - read:orders post: summary: Create order shipment description: Creates a shipment for an order operationId: createOrderShipment tags: - orders requestBody: description: Shipment to create required: true content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Shipment" examples: shipment: summary: Example of a shipment value: id: 0 orderId: 1 status: pending carrier: ups estimatedDelivery: "2023-01-05" responses: '201': description: Shipment created headers: Location: description: URL of the newly created shipment schema: type: string format: uri content: application/json: schema: $ref: "../schemas/order-schemas.yaml#/Shipment" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Order not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - order_auth: - write:orders ================================================ FILE: modules/swagger-core/src/test/resources/comprehensiveOAS31/paths/pet-paths.yaml ================================================ # Pet Paths for OpenAPI 3.1 # This file contains pet-related paths referenced by the root file # Path for /pets /pets: get: summary: List all pets description: Returns all pets from the system that the user has access to operationId: listPets tags: - pets parameters: - name: limit in: query description: Maximum number of pets to return required: false schema: type: integer format: int32 minimum: 1 maximum: 100 default: 20 - name: offset in: query description: Offset for pagination required: false schema: type: integer format: int32 minimum: 0 default: 0 - name: status in: query description: Status values that need to be considered for filter required: false schema: type: string enum: [available, pending, sold] - name: tags in: query description: Tags to filter by required: false schema: type: array items: type: string minItems: 1 maxItems: 10 uniqueItems: true - name: sort in: query description: Sort order required: false schema: type: string enum: [name, id, status] default: name responses: '200': description: A paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string format: uri x-total-count: description: Total number of pets schema: type: integer format: int32 minimum: 0 content: application/json: schema: $ref: "../schemas/pet-schemas.yaml#/Pets" examples: pets: summary: Example of pets value: - id: 1 name: Fluffy status: available - id: 2 name: Rex status: pending '400': description: Bad request content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '401': description: Unauthorized content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '403': description: Forbidden content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - petstore_auth: - read:pets post: summary: Create a pet description: Creates a new pet in the store operationId: createPet tags: - pets requestBody: description: Pet to add to the store required: true content: application/json: schema: $ref: "../schemas/pet-schemas.yaml#/Pet" examples: pet: summary: Example of a pet value: id: 0 name: Fluffy status: available responses: '201': description: Pet created headers: Location: description: URL of the newly created pet schema: type: string format: uri content: application/json: schema: $ref: "../schemas/pet-schemas.yaml#/Pet" '400': description: Bad request content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '401': description: Unauthorized content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '403': description: Forbidden content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - petstore_auth: - write:pets # Path for /pets/{petId} /pets/{petId}: parameters: - name: petId in: path description: ID of pet to return required: true schema: type: integer format: int64 minimum: 1 get: summary: Find pet by ID description: Returns a single pet operationId: getPetById tags: - pets responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/pet-schemas.yaml#/Pet" examples: pet: summary: Example of a pet value: id: 1 name: Fluffy status: available '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Pet not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - petstore_auth: - read:pets - api_key: [] put: summary: Update an existing pet description: Updates a pet in the store with form data operationId: updatePet tags: - pets requestBody: description: Pet to update required: true content: application/json: schema: $ref: "../schemas/pet-schemas.yaml#/Pet" examples: pet: summary: Example of a pet value: id: 1 name: Fluffy status: available responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/pet-schemas.yaml#/Pet" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Pet not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '405': description: Validation exception content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - petstore_auth: - write:pets delete: summary: Deletes a pet description: Deletes a pet from the store operationId: deletePet tags: - pets responses: '204': description: Pet deleted '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Pet not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - petstore_auth: - write:pets # Path for /pets/findByStatus /pets/findByStatus: get: summary: Finds pets by status description: Multiple status values can be provided with comma separated strings operationId: findPetsByStatus tags: - pets parameters: - name: status in: query description: Status values that need to be considered for filter required: true schema: type: array items: type: string enum: [available, pending, sold] minItems: 1 maxItems: 3 uniqueItems: true style: form explode: false responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/pet-schemas.yaml#/Pets" '400': description: Invalid status value content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - petstore_auth: - read:pets # Path for /pets/findByTags /pets/findByTags: get: summary: Finds pets by tags description: Multiple tags can be provided with comma separated strings operationId: findPetsByTags tags: - pets parameters: - name: tags in: query description: Tags to filter by required: true schema: type: array items: type: string minItems: 1 maxItems: 10 uniqueItems: true style: form explode: false responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/pet-schemas.yaml#/Pets" '400': description: Invalid tag value content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - petstore_auth: - read:pets deprecated: true # Path for /pets/{petId}/uploadImage /pets/{petId}/uploadImage: parameters: - name: petId in: path description: ID of pet to update required: true schema: type: integer format: int64 minimum: 1 post: summary: Uploads an image for a pet description: Uploads an image for a pet operationId: uploadPetImage tags: - pets requestBody: content: multipart/form-data: schema: type: object properties: additionalMetadata: type: string description: Additional data to pass to server file: type: string format: binary description: File to upload responses: '200': description: Successful operation content: application/json: schema: type: object properties: code: type: integer format: int32 type: type: string message: type: string '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: Pet not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - petstore_auth: - write:pets ================================================ FILE: modules/swagger-core/src/test/resources/comprehensiveOAS31/paths/user-paths.yaml ================================================ # User Paths for OpenAPI 3.1 # This file contains user-related paths referenced by the root file # Path for /users /users: get: summary: List all users description: Returns all users from the system that the requester has access to operationId: listUsers tags: - users parameters: - name: limit in: query description: Maximum number of users to return required: false schema: type: integer format: int32 minimum: 1 maximum: 100 default: 20 - name: offset in: query description: Offset for pagination required: false schema: type: integer format: int32 minimum: 0 default: 0 - name: status in: query description: Status values that need to be considered for filter required: false schema: type: integer format: int32 enum: [0, 1, 2] - name: sort in: query description: Sort order required: false schema: type: string enum: [username, id, status] default: username responses: '200': description: A paged array of users headers: x-next: description: A link to the next page of responses schema: type: string format: uri x-total-count: description: Total number of users schema: type: integer format: int32 minimum: 0 content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/UserArray" examples: users: summary: Example of users value: - id: 1 username: john_doe email: john@example.com - id: 2 username: jane_doe email: jane@example.com '400': description: Bad request content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '401': description: Unauthorized content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '403': description: Forbidden content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - user_auth: - read:users post: summary: Create a user description: Creates a new user in the system operationId: createUser tags: - users requestBody: description: User to add to the system required: true content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/User" examples: user: summary: Example of a user value: id: 0 username: john_doe firstName: John lastName: Doe email: john@example.com password: password123 phone: "+1234567890" userStatus: 0 responses: '201': description: User created headers: Location: description: URL of the newly created user schema: type: string format: uri content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/User" '400': description: Bad request content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '401': description: Unauthorized content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '403': description: Forbidden content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - user_auth: - write:users # Path for /users/{userId} /users/{userId}: parameters: - name: userId in: path description: ID of user to return required: true schema: type: integer format: int64 minimum: 1 get: summary: Find user by ID description: Returns a single user operationId: getUserById tags: - users responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/User" examples: user: summary: Example of a user value: id: 1 username: john_doe firstName: John lastName: Doe email: john@example.com phone: "+1234567890" userStatus: 0 '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: User not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - user_auth: - read:users - api_key: [] put: summary: Update an existing user description: Updates a user in the system operationId: updateUser tags: - users requestBody: description: User to update required: true content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/User" examples: user: summary: Example of a user value: id: 1 username: john_doe firstName: John lastName: Doe email: john@example.com phone: "+1234567890" userStatus: 0 responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/User" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: User not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '405': description: Validation exception content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - user_auth: - write:users delete: summary: Deletes a user description: Deletes a user from the system operationId: deleteUser tags: - users responses: '204': description: User deleted '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: User not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - user_auth: - write:users # Path for /users/login /users/login: post: summary: User login description: Logs user into the system operationId: loginUser tags: - users requestBody: description: User credentials required: true content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/UserCredentials" examples: credentials: summary: Example of user credentials value: username: john_doe password: password123 responses: '200': description: Successful operation headers: X-Rate-Limit: description: Calls per hour allowed by the user schema: type: integer format: int32 X-Expires-After: description: Date in UTC when token expires schema: type: string format: date-time content: application/json: schema: type: object properties: token: type: string description: Authentication token expiresAt: type: string format: date-time description: Token expiration time '400': description: Invalid username/password supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" # Path for /users/logout /users/logout: post: summary: User logout description: Logs out current logged in user session operationId: logoutUser tags: - users responses: '200': description: Successful operation '401': description: Unauthorized content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - user_auth: [] # Path for /users/{userId}/preferences /users/{userId}/preferences: parameters: - name: userId in: path description: ID of user to return preferences for required: true schema: type: integer format: int64 minimum: 1 get: summary: Get user preferences description: Returns user preferences operationId: getUserPreferences tags: - users responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/UserPreferences" examples: preferences: summary: Example of user preferences value: theme: dark language: en notifications: email: true push: true sms: false timezone: UTC currency: USD '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: User not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - user_auth: - read:users put: summary: Update user preferences description: Updates user preferences operationId: updateUserPreferences tags: - users requestBody: description: User preferences to update required: true content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/UserPreferences" examples: preferences: summary: Example of user preferences value: theme: dark language: en notifications: email: true push: true sms: false timezone: UTC currency: USD responses: '200': description: Successful operation content: application/json: schema: $ref: "../schemas/user-schemas.yaml#/UserPreferences" '400': description: Invalid ID supplied content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '404': description: User not found content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" '500': description: Internal server error content: application/json: schema: $ref: "../schemas/common-schemas.yaml#/Error" security: - user_auth: - write:users ================================================ FILE: modules/swagger-core/src/test/resources/comprehensiveOAS31/schemas/common-schemas.yaml ================================================ # Common Schemas for OpenAPI 3.1 and JSON Schema 2020/12 # This file contains common schemas referenced by the root file # Basic schema with JSON Schema 2020/12 keywords Error: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Error" $anchor: "Error" title: "Error" description: "Error response" type: "object" required: - "code" - "message" properties: code: type: "integer" format: "int32" description: "Error code" minimum: 100 maximum: 600 message: type: "string" description: "Error message" minLength: 1 details: type: "array" description: "Error details" items: type: "string" minItems: 0 maxItems: 10 uniqueItems: true # Schema with $dynamicAnchor and $dynamicRef Identifiable: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Identifiable" $dynamicAnchor: "Identifiable" title: "Identifiable" description: "Base schema for objects with an ID" type: "object" required: - "id" properties: id: type: "string" format: "uuid" description: "Unique identifier" # Schema with $vocabulary ExtendedSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/ExtendedSchema" $vocabulary: "https://json-schema.org/draft/2020-12/vocab/core": true "https://json-schema.org/draft/2020-12/vocab/applicator": true "https://json-schema.org/draft/2020-12/vocab/validation": true "https://json-schema.org/draft/2020-12/vocab/meta-data": true "https://json-schema.org/draft/2020-12/vocab/format-annotation": true "https://json-schema.org/draft/2020-12/vocab/content": true "https://json-schema.org/draft/2020-12/vocab/unevaluated": true title: "Extended Schema" description: "Schema with vocabulary" type: "object" properties: name: type: "string" value: type: "string" # Schema with $comment CommentedSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/CommentedSchema" $comment: "This is a schema with comments" title: "Commented Schema" description: "Schema with comments" type: "object" properties: name: $comment: "The name property" type: "string" value: $comment: "The value property" type: "string" # Schema with $defs SchemaWithDefs: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/SchemaWithDefs" title: "Schema with Definitions" description: "Schema with $defs" type: "object" properties: person: $ref: "#/$defs/Person" address: $ref: "#/$defs/Address" $defs: Person: type: "object" properties: firstName: type: "string" lastName: type: "string" age: type: "integer" minimum: 0 Address: type: "object" properties: street: type: "string" city: type: "string" zipCode: type: "string" pattern: "^[0-9]{5}(?:-[0-9]{4})?$" # Schema with validation keywords ValidationSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/ValidationSchema" title: "Validation Schema" description: "Schema with validation keywords" type: "object" required: - "name" - "email" properties: name: type: "string" minLength: 1 maxLength: 100 email: type: "string" format: "email" pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" age: type: "integer" minimum: 0 maximum: 120 exclusiveMaximum: 121 score: type: "number" multipleOf: 0.5 minimum: 0 maximum: 10 tags: type: "array" items: type: "string" minItems: 0 maxItems: 10 uniqueItems: true metadata: type: "object" minProperties: 0 maxProperties: 10 propertyNames: pattern: "^[a-zA-Z0-9_]+$" status: enum: ["active", "inactive", "pending"] role: const: "user" # Schema with applicator keywords ApplicatorSchema: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/ApplicatorSchema" title: "Applicator Schema" description: "Schema with applicator keywords" allOf: - type: "object" properties: id: type: "string" format: "uuid" - required: - "name" anyOf: - properties: type: const: "personal" - properties: type: const: "business" oneOf: - properties: status: const: "active" - properties: status: const: "inactive" not: properties: status: const: "deleted" if: properties: type: const: "personal" then: properties: personalId: type: "string" required: - "personalId" else: properties: businessId: type: "string" required: - "businessId" dependentSchemas: creditCard: properties: creditCardNumber: type: "string" pattern: "^[0-9]{16}$" required: - "creditCardNumber" properties: name: type: "string" type: type: "string" status: type: "string" items: type: "array" prefixItems: - type: "string" - type: "number" items: false contains: type: "array" contains: type: "string" const: "special" minContains: 1 maxContains: 3 patternProperties: "^x-": type: "string" additionalProperties: false unevaluatedProperties: false ================================================ FILE: modules/swagger-core/src/test/resources/comprehensiveOAS31/schemas/json-schema.yaml ================================================ # JSON Schema 2020/12 Example # This file demonstrates a comprehensive JSON Schema 2020/12 document # It includes all keywords defined in the JSON Schema 2020/12 specification $schema: https://json-schema.org/draft/2020-12/schema $id: https://example.com/schemas/json-schema $vocabulary: https://json-schema.org/draft/2020-12/vocab/core: true https://json-schema.org/draft/2020-12/vocab/applicator: true https://json-schema.org/draft/2020-12/vocab/validation: true https://json-schema.org/draft/2020-12/vocab/meta-data: true https://json-schema.org/draft/2020-12/vocab/format-annotation: true https://json-schema.org/draft/2020-12/vocab/content: true https://json-schema.org/draft/2020-12/vocab/unevaluated: true $comment: This is a comprehensive JSON Schema 2020/12 document # Root schema title: Comprehensive JSON Schema description: A comprehensive JSON Schema 2020/12 document type: object properties: id: $anchor: id title: ID description: Unique identifier type: string format: uuid name: $anchor: name title: Name description: Name of the entity type: string minLength: 1 maxLength: 100 description: $anchor: description title: Description description: Description of the entity type: string maxLength: 1000 createdAt: $anchor: createdAt title: Created At description: Creation date type: string format: date-time updatedAt: $anchor: updatedAt title: Updated At description: Last update date type: string format: date-time tags: $anchor: tags title: Tags description: Tags for the entity type: array items: type: string minLength: 1 maxLength: 50 minItems: 0 maxItems: 10 uniqueItems: true metadata: $anchor: metadata title: Metadata description: Additional metadata type: object additionalProperties: type: string propertyNames: pattern: "^[a-zA-Z0-9_]+$" minProperties: 0 maxProperties: 10 status: $anchor: status title: Status description: Status of the entity type: string enum: ["active", "inactive", "pending", "deleted"] priority: $anchor: priority title: Priority description: Priority of the entity type: integer minimum: 1 maximum: 5 default: 3 score: $anchor: score title: Score description: Score of the entity type: number minimum: 0 maximum: 100 multipleOf: 0.1 isPublic: $anchor: isPublic title: Is Public description: Whether the entity is public type: boolean default: false nullableField: $anchor: nullableField title: Nullable Field description: A field that can be null type: ["string", "null"] constField: $anchor: constField title: Const Field description: A field with a constant value const: "constant" contentField: $anchor: contentField title: Content Field description: A field with content encoding and media type type: string contentEncoding: base64 contentMediaType: image/png dependentField1: $anchor: dependentField1 title: Dependent Field 1 description: A field that depends on another field type: string dependentField2: $anchor: dependentField2 title: Dependent Field 2 description: A field that depends on another field type: string conditionalField: $anchor: conditionalField title: Conditional Field description: A field that is conditional type: string refField: $anchor: refField title: Ref Field description: A field that references another schema $ref: "#/$defs/RefSchema" dynamicRefField: $anchor: dynamicRefField title: Dynamic Ref Field description: A field that uses dynamic reference $dynamicRef: "#Entity" recursiveField: $anchor: recursiveField title: Recursive Field description: A field that references itself $ref: "#" prefixItems: $anchor: prefixItems title: Prefix Items description: An array with prefix items type: array prefixItems: - type: string - type: number - type: boolean items: false containsField: $anchor: containsField title: Contains Field description: An array that contains a specific item type: array contains: type: string const: "special" minContains: 1 maxContains: 3 patternProperties: $anchor: patternProperties title: Pattern Properties description: An object with pattern properties type: object patternProperties: "^x-": type: string "^y-": type: number additionalProperties: false unevaluatedProperties: $anchor: unevaluatedProperties title: Unevaluated Properties description: An object with unevaluated properties type: object properties: prop1: type: string unevaluatedProperties: false unevaluatedItems: $anchor: unevaluatedItems title: Unevaluated Items description: An array with unevaluated items type: array prefixItems: - type: string unevaluatedItems: false required: - id - name - createdAt dependentRequired: dependentField1: ["dependentField2"] dependentSchemas: isPublic: properties: publicationDate: type: string format: date required: - publicationDate # Conditional validation if: properties: status: const: "active" required: - status then: properties: activatedAt: type: string format: date-time required: - activatedAt else: properties: deactivatedAt: type: string format: date-time # Applicator keywords allOf: - properties: allOfField: type: string required: - allOfField anyOf: - properties: anyOfField1: type: string required: - anyOfField1 - properties: anyOfField2: type: string required: - anyOfField2 oneOf: - properties: oneOfField1: type: string required: - oneOfField1 - properties: oneOfField2: type: string required: - oneOfField2 not: properties: notField: type: string required: - notField # Definitions $defs: RefSchema: $anchor: RefSchema title: Ref Schema description: A schema that is referenced type: object properties: id: type: string format: uuid name: type: string minLength: 1 maxLength: 100 required: - id - name Entity: $dynamicAnchor: Entity title: Entity description: A base entity schema type: object properties: id: type: string format: uuid name: type: string minLength: 1 maxLength: 100 createdAt: type: string format: date-time updatedAt: type: string format: date-time required: - id - name - createdAt Person: $anchor: Person title: Person description: A person schema allOf: - $dynamicRef: "#Entity" - type: object properties: firstName: type: string minLength: 1 maxLength: 50 lastName: type: string minLength: 1 maxLength: 50 email: type: string format: email phone: type: string pattern: "^\\+?[0-9]{10,15}$" required: - firstName - lastName - email Organization: $anchor: Organization title: Organization description: An organization schema allOf: - $dynamicRef: "#Entity" - type: object properties: legalName: type: string minLength: 1 maxLength: 100 taxId: type: string minLength: 1 maxLength: 50 website: type: string format: uri employees: type: integer minimum: 1 required: - legalName Address: $anchor: Address title: Address description: An address schema type: object properties: street: type: string minLength: 1 maxLength: 100 city: type: string minLength: 1 maxLength: 50 state: type: string minLength: 1 maxLength: 50 zipCode: type: string pattern: "^[0-9]{5}(?:-[0-9]{4})?$" country: type: string minLength: 1 maxLength: 50 required: - street - city - zipCode - country Contact: $anchor: Contact title: Contact description: A contact schema type: object properties: name: type: string minLength: 1 maxLength: 100 email: type: string format: email phone: type: string pattern: "^\\+?[0-9]{10,15}$" address: $ref: "#/$defs/Address" required: - name - email Event: $anchor: Event title: Event description: An event schema type: object properties: id: type: string format: uuid name: type: string minLength: 1 maxLength: 100 description: type: string maxLength: 1000 startDate: type: string format: date-time endDate: type: string format: date-time location: $ref: "#/$defs/Address" organizer: $ref: "#/$defs/Contact" attendees: type: array items: $ref: "#/$defs/Contact" minItems: 0 maxItems: 1000 uniqueItems: true required: - id - name - startDate - endDate ================================================ FILE: modules/swagger-core/src/test/resources/comprehensiveOAS31/schemas/order-schemas.yaml ================================================ # Order Schemas for OpenAPI 3.1 and JSON Schema 2020/12 # This file contains order-related schemas referenced by the root file # Base Order schema Order: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Order" $anchor: "Order" $dynamicAnchor: "Order" title: "Order" description: "Order object" type: "object" required: - "id" - "petId" - "quantity" - "shipDate" - "status" properties: id: type: "integer" format: "int64" description: "Order ID" minimum: 1 petId: type: "integer" format: "int64" description: "Pet ID" minimum: 1 userId: type: "integer" format: "int64" description: "User ID" minimum: 1 quantity: type: "integer" format: "int32" description: "Order quantity" minimum: 1 maximum: 100 shipDate: type: "string" format: "date-time" description: "Shipping date" status: type: "string" description: "Order status" enum: ["placed", "approved", "delivered", "cancelled"] complete: type: "boolean" description: "Whether the order is complete" default: false createdAt: type: "string" format: "date-time" description: "Order creation date" readOnly: true updatedAt: type: "string" format: "date-time" description: "Order last update date" readOnly: true additionalProperties: false x-extension-example: "Example of an extension" # OrderItem schema OrderItem: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/OrderItem" $anchor: "OrderItem" title: "Order Item" description: "Order item object" type: "object" required: - "id" - "petId" - "quantity" - "price" properties: id: type: "integer" format: "int64" description: "Order item ID" minimum: 1 petId: type: "integer" format: "int64" description: "Pet ID" minimum: 1 quantity: type: "integer" format: "int32" description: "Item quantity" minimum: 1 maximum: 100 price: type: "number" format: "double" description: "Item price" minimum: 0 exclusiveMinimum: true discount: type: "number" format: "double" description: "Item discount" minimum: 0 maximum: 100 default: 0 notes: type: "string" description: "Additional notes" maxLength: 500 # OrderWithItems schema OrderWithItems: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/OrderWithItems" $anchor: "OrderWithItems" title: "Order with Items" description: "Order object with items" allOf: - $ref: "#/Order" - type: "object" properties: items: type: "array" description: "Order items" items: $ref: "#/OrderItem" minItems: 1 maxItems: 100 uniqueItems: true required: - "items" # OrderStatus schema OrderStatus: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/OrderStatus" $anchor: "OrderStatus" title: "Order Status" description: "Order status object" type: "object" required: - "id" - "status" properties: id: type: "integer" format: "int64" description: "Order ID" minimum: 1 status: type: "string" description: "Order status" enum: ["placed", "approved", "delivered", "cancelled"] timestamp: type: "string" format: "date-time" description: "Status update timestamp" readOnly: true notes: type: "string" description: "Status notes" maxLength: 500 # OrderArray schema OrderArray: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/OrderArray" $anchor: "OrderArray" title: "Order Array" description: "Array of orders" type: "array" items: $ref: "#/Order" minItems: 0 maxItems: 100 uniqueItems: true # OrderSummary schema OrderSummary: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/OrderSummary" $anchor: "OrderSummary" title: "Order Summary" description: "Order summary object" type: "object" required: - "id" - "petId" - "status" - "createdAt" properties: id: type: "integer" format: "int64" description: "Order ID" minimum: 1 petId: type: "integer" format: "int64" description: "Pet ID" minimum: 1 status: type: "string" description: "Order status" enum: ["placed", "approved", "delivered", "cancelled"] createdAt: type: "string" format: "date-time" description: "Order creation date" readOnly: true additionalProperties: false # Invoice schema Invoice: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Invoice" $anchor: "Invoice" title: "Invoice" description: "Invoice object" type: "object" required: - "id" - "orderId" - "amount" - "status" - "createdAt" properties: id: type: "integer" format: "int64" description: "Invoice ID" minimum: 1 orderId: type: "integer" format: "int64" description: "Order ID" minimum: 1 amount: type: "number" format: "double" description: "Invoice amount" minimum: 0 exclusiveMinimum: true tax: type: "number" format: "double" description: "Tax amount" minimum: 0 default: 0 shipping: type: "number" format: "double" description: "Shipping amount" minimum: 0 default: 0 total: type: "number" format: "double" description: "Total amount" minimum: 0 exclusiveMinimum: true status: type: "string" description: "Invoice status" enum: ["pending", "paid", "cancelled"] paymentMethod: type: "string" description: "Payment method" enum: ["credit_card", "debit_card", "paypal", "bank_transfer", "cash"] createdAt: type: "string" format: "date-time" description: "Invoice creation date" readOnly: true paidAt: type: "string" format: "date-time" description: "Invoice payment date" readOnly: true additionalProperties: false # Payment schema Payment: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Payment" $anchor: "Payment" title: "Payment" description: "Payment object" type: "object" required: - "id" - "invoiceId" - "amount" - "method" - "status" - "createdAt" properties: id: type: "integer" format: "int64" description: "Payment ID" minimum: 1 invoiceId: type: "integer" format: "int64" description: "Invoice ID" minimum: 1 amount: type: "number" format: "double" description: "Payment amount" minimum: 0 exclusiveMinimum: true method: type: "string" description: "Payment method" enum: ["credit_card", "debit_card", "paypal", "bank_transfer", "cash"] status: type: "string" description: "Payment status" enum: ["pending", "completed", "failed", "refunded"] transactionId: type: "string" description: "Payment transaction ID" minLength: 1 maxLength: 100 createdAt: type: "string" format: "date-time" description: "Payment creation date" readOnly: true completedAt: type: "string" format: "date-time" description: "Payment completion date" readOnly: true additionalProperties: false # Shipment schema Shipment: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Shipment" $anchor: "Shipment" title: "Shipment" description: "Shipment object" type: "object" required: - "id" - "orderId" - "status" - "createdAt" properties: id: type: "integer" format: "int64" description: "Shipment ID" minimum: 1 orderId: type: "integer" format: "int64" description: "Order ID" minimum: 1 status: type: "string" description: "Shipment status" enum: ["pending", "shipped", "delivered", "returned"] trackingNumber: type: "string" description: "Shipment tracking number" minLength: 1 maxLength: 100 carrier: type: "string" description: "Shipping carrier" enum: ["ups", "fedex", "dhl", "usps"] estimatedDelivery: type: "string" format: "date" description: "Estimated delivery date" actualDelivery: type: "string" format: "date" description: "Actual delivery date" createdAt: type: "string" format: "date-time" description: "Shipment creation date" readOnly: true shippedAt: type: "string" format: "date-time" description: "Shipment shipping date" readOnly: true deliveredAt: type: "string" format: "date-time" description: "Shipment delivery date" readOnly: true additionalProperties: false ================================================ FILE: modules/swagger-core/src/test/resources/comprehensiveOAS31/schemas/pet-schemas.yaml ================================================ # Pet Schemas for OpenAPI 3.1 and JSON Schema 2020/12 # This file contains pet-related schemas referenced by the root file # Base Pet schema Pet: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Pet" $anchor: "Pet" $dynamicAnchor: "Pet" title: "Pet" description: "Pet object" type: "object" required: - "id" - "name" - "status" properties: id: type: "integer" format: "int64" description: "Pet ID" minimum: 1 name: type: "string" description: "Pet name" minLength: 1 maxLength: 100 category: $ref: "#/Category" photoUrls: type: "array" description: "Pet photo URLs" items: type: "string" format: "uri" minItems: 0 maxItems: 10 uniqueItems: true tags: type: "array" description: "Pet tags" items: $ref: "#/Tag" minItems: 0 maxItems: 10 uniqueItems: true status: type: "string" description: "Pet status in the store" enum: ["available", "pending", "sold"] metadata: type: "object" description: "Additional metadata" additionalProperties: type: "string" propertyNames: pattern: "^[a-zA-Z0-9_]+$" minProperties: 0 maxProperties: 10 discriminator: propertyName: "petType" mapping: "dog": "#/Dog" "cat": "#/Cat" "bird": "#/Bird" x-extension-example: "Example of an extension" # Category schema Category: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Category" $anchor: "Category" title: "Category" description: "Pet category" type: "object" required: - "id" - "name" properties: id: type: "integer" format: "int64" description: "Category ID" minimum: 1 name: type: "string" description: "Category name" minLength: 1 maxLength: 50 # Tag schema Tag: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Tag" $anchor: "Tag" title: "Tag" description: "Pet tag" type: "object" required: - "id" - "name" properties: id: type: "integer" format: "int64" description: "Tag ID" minimum: 1 name: type: "string" description: "Tag name" minLength: 1 maxLength: 50 # Dog schema Dog: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Dog" $anchor: "Dog" title: "Dog" description: "Dog object" allOf: - $ref: "#/Pet" - type: "object" required: - "petType" - "breed" properties: petType: type: "string" const: "dog" breed: type: "string" description: "Dog breed" minLength: 1 maxLength: 50 bark: type: "boolean" description: "Whether the dog can bark" default: true vaccinated: type: "boolean" description: "Whether the dog is vaccinated" default: false # Cat schema Cat: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Cat" $anchor: "Cat" title: "Cat" description: "Cat object" allOf: - $ref: "#/Pet" - type: "object" required: - "petType" - "breed" properties: petType: type: "string" const: "cat" breed: type: "string" description: "Cat breed" minLength: 1 maxLength: 50 declawed: type: "boolean" description: "Whether the cat is declawed" default: false indoor: type: "boolean" description: "Whether the cat is an indoor cat" default: true # Bird schema Bird: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Bird" $anchor: "Bird" title: "Bird" description: "Bird object" allOf: - $ref: "#/Pet" - type: "object" required: - "petType" - "species" properties: petType: type: "string" const: "bird" species: type: "string" description: "Bird species" minLength: 1 maxLength: 50 canFly: type: "boolean" description: "Whether the bird can fly" default: true canTalk: type: "boolean" description: "Whether the bird can talk" default: false # Pets array schema Pets: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Pets" $anchor: "Pets" title: "Pets" description: "Array of pets" type: "array" items: $ref: "#/Pet" minItems: 0 maxItems: 100 uniqueItems: true # Pet with validation PetWithValidation: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/PetWithValidation" $anchor: "PetWithValidation" title: "Pet with Validation" description: "Pet object with additional validation" allOf: - $ref: "#/Pet" - type: "object" properties: age: type: "integer" description: "Pet age in years" minimum: 0 maximum: 30 weight: type: "number" description: "Pet weight in kilograms" minimum: 0.1 maximum: 100 multipleOf: 0.1 height: type: "number" description: "Pet height in centimeters" minimum: 1 maximum: 200 multipleOf: 0.1 birthDate: type: "string" format: "date" description: "Pet birth date" microchipped: type: "boolean" description: "Whether the pet is microchipped" default: false dependentRequired: microchipped: ["microchipNumber"] dependentSchemas: microchipped: properties: microchipNumber: type: "string" description: "Microchip number" pattern: "^[0-9]{15}$" required: - "microchipNumber" # Pet with conditional schema PetWithConditional: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/PetWithConditional" $anchor: "PetWithConditional" title: "Pet with Conditional Schema" description: "Pet object with conditional schema" allOf: - $ref: "#/Pet" - type: "object" properties: type: type: "string" enum: ["domestic", "wild"] dangerous: type: "boolean" description: "Whether the pet is dangerous" if: properties: type: const: "wild" required: - "type" then: properties: dangerous: const: true required: - "dangerous" else: properties: dangerous: default: false ================================================ FILE: modules/swagger-core/src/test/resources/comprehensiveOAS31/schemas/user-schemas.yaml ================================================ # User Schemas for OpenAPI 3.1 and JSON Schema 2020/12 # This file contains user-related schemas referenced by the root file # Base User schema User: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/User" $anchor: "User" $dynamicAnchor: "User" title: "User" description: "User object" type: "object" required: - "id" - "username" - "email" properties: id: type: "integer" format: "int64" description: "User ID" minimum: 1 username: type: "string" description: "User name" minLength: 3 maxLength: 50 pattern: "^[a-zA-Z0-9_]+$" firstName: type: "string" description: "User first name" minLength: 1 maxLength: 50 lastName: type: "string" description: "User last name" minLength: 1 maxLength: 50 email: type: "string" format: "email" description: "User email" pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" password: type: "string" description: "User password" minLength: 8 maxLength: 100 writeOnly: true phone: type: "string" description: "User phone number" pattern: "^\\+?[0-9]{10,15}$" userStatus: type: "integer" format: "int32" description: "User status" enum: [0, 1, 2] default: 0 address: $ref: "#/Address" createdAt: type: "string" format: "date-time" description: "User creation date" readOnly: true updatedAt: type: "string" format: "date-time" description: "User last update date" readOnly: true additionalProperties: false x-extension-example: "Example of an extension" # Address schema Address: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Address" $anchor: "Address" title: "Address" description: "User address" type: "object" properties: street: type: "string" description: "Street address" minLength: 1 maxLength: 100 city: type: "string" description: "City" minLength: 1 maxLength: 50 state: type: "string" description: "State or province" minLength: 1 maxLength: 50 zipCode: type: "string" description: "Zip code" pattern: "^[0-9]{5}(?:-[0-9]{4})?$" country: type: "string" description: "Country" minLength: 1 maxLength: 50 required: - "street" - "city" - "zipCode" - "country" # UserArray schema UserArray: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/UserArray" $anchor: "UserArray" title: "User Array" description: "Array of users" type: "array" items: $ref: "#/User" minItems: 0 maxItems: 100 uniqueItems: true # UserWithRoles schema UserWithRoles: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/UserWithRoles" $anchor: "UserWithRoles" title: "User with Roles" description: "User object with roles" allOf: - $ref: "#/User" - type: "object" properties: roles: type: "array" description: "User roles" items: $ref: "#/Role" minItems: 1 maxItems: 10 uniqueItems: true required: - "roles" # Role schema Role: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Role" $anchor: "Role" title: "Role" description: "User role" type: "object" properties: id: type: "integer" format: "int32" description: "Role ID" minimum: 1 name: type: "string" description: "Role name" enum: ["admin", "user", "moderator", "guest"] description: type: "string" description: "Role description" minLength: 1 maxLength: 200 permissions: type: "array" description: "Role permissions" items: $ref: "#/Permission" minItems: 0 maxItems: 50 uniqueItems: true required: - "id" - "name" # Permission schema Permission: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/Permission" $anchor: "Permission" title: "Permission" description: "User permission" type: "object" properties: id: type: "integer" format: "int32" description: "Permission ID" minimum: 1 name: type: "string" description: "Permission name" minLength: 1 maxLength: 50 description: type: "string" description: "Permission description" minLength: 1 maxLength: 200 required: - "id" - "name" # UserCredentials schema UserCredentials: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/UserCredentials" $anchor: "UserCredentials" title: "User Credentials" description: "User credentials for authentication" type: "object" properties: username: type: "string" description: "User name" minLength: 3 maxLength: 50 pattern: "^[a-zA-Z0-9_]+$" password: type: "string" description: "User password" minLength: 8 maxLength: 100 writeOnly: true required: - "username" - "password" additionalProperties: false # UserPreferences schema UserPreferences: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/UserPreferences" $anchor: "UserPreferences" title: "User Preferences" description: "User preferences" type: "object" properties: theme: type: "string" description: "UI theme" enum: ["light", "dark", "system"] default: "system" language: type: "string" description: "UI language" enum: ["en", "fr", "es", "de", "it", "ja", "zh"] default: "en" notifications: type: "object" description: "Notification preferences" properties: email: type: "boolean" description: "Email notifications" default: true push: type: "boolean" description: "Push notifications" default: true sms: type: "boolean" description: "SMS notifications" default: false additionalProperties: false timezone: type: "string" description: "User timezone" default: "UTC" currency: type: "string" description: "Preferred currency" enum: ["USD", "EUR", "GBP", "JPY", "CAD", "AUD"] default: "USD" additionalProperties: false # UserWithPreferences schema UserWithPreferences: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/UserWithPreferences" $anchor: "UserWithPreferences" title: "User with Preferences" description: "User object with preferences" allOf: - $ref: "#/User" - type: "object" properties: preferences: $ref: "#/UserPreferences" ================================================ FILE: modules/swagger-core/src/test/resources/converting/ArrayOfSubclassTest_expected30.json ================================================ { "schema" : { "description" : "The holder", "properties" : { "name" : { "type" : "string" }, "friend" : { "type" : "string" }, "baseArray" : { "type" : "array", "description" : "Thingy", "items" : { "$ref" : "#/components/schemas/Base" }, "minItems" : 0, "uniqueItems" : true } } }, "referencedSchemas" : { "Base" : { "description" : "Stuff", "discriminator" : { "propertyName" : "name", "mapping" : { "a" : "#/components/schemas/SubA", "b" : "#/components/schemas/SubB" } }, "properties" : { "name" : { "type" : "string" } } }, "Holder" : { "description" : "The holder", "properties" : { "name" : { "type" : "string" }, "friend" : { "type" : "string" }, "baseArray" : { "type" : "array", "description" : "Thingy", "items" : { "$ref" : "#/components/schemas/Base" }, "minItems" : 0, "uniqueItems" : true } } }, "SubA" : { "description" : "The SubA class", "properties" : { "name" : { "type" : "string" }, "count" : { "type" : "integer", "format" : "int64" } } }, "SubB" : { "description" : "The SubB class", "properties" : { "name" : { "type" : "string" }, "friend" : { "type" : "string" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/converting/ArrayOfSubclassTest_expected31.json ================================================ { "schema" : { "type" : "object", "description" : "The holder", "properties" : { "name" : { "type" : "string" }, "friend" : { "type" : "string" }, "baseArray" : { "type" : "array", "description" : "Thingy", "items" : { "$ref" : "#/components/schemas/Base" }, "minItems" : 0, "uniqueItems" : true } } }, "referencedSchemas" : { "Base" : { "type" : "object", "description" : "Stuff", "discriminator" : { "propertyName" : "name", "mapping" : { "a" : "#/components/schemas/SubA", "b" : "#/components/schemas/SubB" } }, "properties" : { "name" : { "type" : "string" } } }, "Holder" : { "type" : "object", "description" : "The holder", "properties" : { "name" : { "type" : "string" }, "friend" : { "type" : "string" }, "baseArray" : { "type" : "array", "description" : "Thingy", "items" : { "$ref" : "#/components/schemas/Base" }, "minItems" : 0, "uniqueItems" : true } } }, "SubA" : { "type" : "object", "description" : "The SubA class", "properties" : { "name" : { "type" : "string" }, "count" : { "type" : "integer", "format" : "int64" } } }, "SubB" : { "type" : "object", "description" : "The SubB class", "properties" : { "name" : { "type" : "string" }, "friend" : { "type" : "string" }, "baseArray" : { "type" : "array", "description" : "Thingy", "items" : { "$ref" : "#/components/schemas/Base" }, "minItems" : 0, "uniqueItems" : true } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/dateSchema.yaml ================================================ openapi: 3.0.3 info: version: "1.0.0" title: Simple Inventory API paths: /inventory: get: operationId: searchInventory parameters: - in: header name: test schema: type: string format: date enum: - 2023-12-12 default: 2023-12-12 responses: '200': description: search results matching criteria content: application/json: schema: type: array items: $ref: '#/components/schemas/InventoryItem' components: schemas: InventoryItem: type: object properties: releaseDate: type: string format: date-time example: '2016-08-29T09:12:33.001Z' ================================================ FILE: modules/swagger-core/src/test/resources/json-schema-validation/array.json ================================================ { "type": "array", "items": { "type": "string" }, "minItems": 1, "maxItems": 10, "uniqueItems": true } ================================================ FILE: modules/swagger-core/src/test/resources/json-schema-validation/map.json ================================================ { "type": "object", "additionalProperties": { "type": "string" }, "minProperties": 1, "maxProperties": 10 } ================================================ FILE: modules/swagger-core/src/test/resources/logback-test.xml ================================================ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/changelog-3.1.yaml ================================================ openapi: "3.1.0" info: version: 1.0.0 title: Swagger Petstore license: name: MIT identifier: test servers: - url: http://petstore.swagger.io/v1 webhooks: # Each webhook needs a name newPet: # This is a Path Item Object, the only difference is that the request is initiated by the API provider post: requestBody: description: Information about a new pet in the system content: application/json: schema: $ref: "#/components/schemas/Pet" responses: "200": description: Return a 200 status to indicate that the data was received successfully paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: "200": description: An paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" post: summary: Create a pet operationId: createPets tags: - pets responses: "201": description: Null response default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById tags: - pets parameters: - name: petId in: path required: true description: The id of the pet to retrieve schema: type: string responses: "200": description: Expected response to a valid request content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" components: schemas: Pet: type: - object - string required: - id - name properties: id: type: integer format: int64 name: type: string testenum: type: string enum: - available - pending - sold default: available testconst: type: string const: pending tag: type: string Pets: type: array items: $ref: "#/components/schemas/Pet" Error: required: - code - message properties: code: type: integer format: int32 message: type: string ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/composed-schema-3.1.json ================================================ { "components": { "schemas": { "SomeChild1ImplObject": { "allOf": [ { "$ref": "#/components/schemas/SomeChildObject" } ] }, "SomeChild2ImplObject": { "allOf": [ { "$ref": "#/components/schemas/SomeChildObject" } ] }, "SomeChildObject": { "description": "Some child object" }, "PatternPropertiesReferencedObject": { "description": "An object schema with is ONLY referenced via pattern properties" }, "SomeParentObject": { "description": "Some parent object", "properties": { "id": { "description": "id", "format": "int64", "type": "integer" }, "other": { "description": "other", "oneOf": [ { "$ref": "#/components/schemas/SomeChild1ImplObject" }, { "$ref": "#/components/schemas/SomeChild2ImplObject" } ] } }, "patternProperties": { "somePattern": { "$ref": "#/components/schemas/PatternPropertiesReferencedObject" } } } } }, "info": { "title": "OpenAPI definition", "version": "v0" }, "openapi": "3.1.0", "paths": { "/some/call": { "get": { "description": "Some operation description", "operationId": "getSome", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SomeParentObject" } } }, "description": "OK" } }, "summary": "Some summary", "tags": [ "Some" ] } } }, "servers": [ { "description": "Generated server url", "url": "http://localhost:8080" } ], "tags": [ { "description": "some actions", "name": "Some" } ] } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/issue-4737-3.1.yaml ================================================ openapi: 3.1.0 info: title: OpenAPI definition version: v0 servers: - url: http://localhost description: Generated server url paths: {} components: schemas: RequestDto: properties: personalNumber: type: string webhooks: newPet: post: requestBody: description: Information about a new pet in the system content: application/json: schema: $ref: "#/components/schemas/RequestDto" description: Webhook Pet responses: '200': description: >- Return a 200 status to indicate that the data was received successfully ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/list-3.1.json ================================================ { "openapi": "3.1.0", "info": { "title": "OpenAPI definition", "version": "v0" }, "paths": { "/some/call": { "get": { "description": "Some operation description", "operationId": "getSome", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SomeParentObject" } } }, "description": "OK" } }, "summary": "Some summary", "tags": [ "Some" ] } } }, "servers": [ { "description": "Generated server url", "url": "http://localhost:8080" } ], "tags": [ { "description": "some actions", "name": "Some" } ], "components": { "schemas": { "SomeChildObject": { "description": "Some child object", "properties": { "id": { "description": "id", "format": "int64", "type": "integer" }, "name": { "description": "name", "type": "string" } } }, "SomeParentObject": { "description": "Some parent object", "properties": { "id": { "description": "id", "format": "int64", "type": "integer" }, "someList": { "description": "list", "items": { "$ref": "#/components/schemas/SomeChildObject" }, "type": "array" } } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/petstore-3.1.json ================================================ { "openapi": "3.1.0", "info": { "version": "1.0.0", "title": "Swagger Petstore", "license": { "name": "MIT", "identifier": "test" } }, "servers": [ { "url": "http://petstore.swagger.io/v1" } ], "webhooks": { "newPet": { "post": { "requestBody": { "description": "Information about a new pet in the system", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } } }, "responses": { "200": { "description": "Return a 200 status to indicate that the data was received successfully" } } } } }, "paths": { "/pets": { "get": { "summary": "List all pets", "operationId": "listPets", "tags": [ "pets" ], "parameters": [ { "name": "limit", "in": "query", "description": "How many items to return at one time (max 100)", "required": false, "schema": { "type": "integer", "format": "int32" } } ], "responses": { "200": { "description": "An paged array of pets", "headers": { "x-next": { "description": "A link to the next page of responses", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pets" } } } }, "default": { "description": "unexpected error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "post": { "summary": "Create a pet", "operationId": "createPets", "tags": [ "pets" ], "responses": { "201": { "description": "Null response" }, "default": { "description": "unexpected error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/pets/{petId}": { "get": { "summary": "Info for a specific pet", "operationId": "showPetById", "tags": [ "pets" ], "parameters": [ { "name": "petId", "in": "path", "required": true, "description": "The id of the pet to retrieve", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Expected response to a valid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pets" } } } }, "default": { "description": "unexpected error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } }, "components": { "schemas": { "Pet": { "required": [ "id", "name" ], "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": [ "string", "integer" ] }, "tag": { "type": "string" } } }, "Pets": { "type": "array", "items": { "$ref": "#/components/schemas/Pet" } }, "Error": { "required": [ "code", "message" ], "properties": { "code": { "type": "integer", "format": "int32" }, "message": { "type": "string" } } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/petstore-3.1.yaml ================================================ openapi: "3.1.0" info: version: 1.0.0 title: Swagger Petstore license: name: MIT identifier: test servers: - url: http://petstore.swagger.io/v1 webhooks: # Each webhook needs a name newPet: # This is a Path Item Object, the only difference is that the request is initiated by the API provider post: requestBody: description: Information about a new pet in the system content: application/json: schema: $ref: "#/components/schemas/Pet" responses: "200": description: Return a 200 status to indicate that the data was received successfully paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: "200": description: An paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" post: summary: Create a pet operationId: createPets tags: - pets responses: "201": description: Null response default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById tags: - pets parameters: - name: petId in: path required: true description: The id of the pet to retrieve schema: type: string responses: "200": description: Expected response to a valid request content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" components: schemas: Pet: required: - id - name properties: id: type: integer format: int64 name: type: - string - integer tag: type: string Pets: type: array items: $ref: "#/components/schemas/Pet" Error: required: - code - message properties: code: type: integer format: int32 message: type: string ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/petstore-3.1_more.yaml ================================================ openapi: "3.1.0" info: version: 1.0.0 title: Swagger Petstore license: name: MIT identifier: test servers: - url: http://petstore.swagger.io/v1 webhooks: # Each webhook needs a name newPet: # This is a Path Item Object, the only difference is that the request is initiated by the API provider post: requestBody: description: Information about a new pet in the system content: application/json: schema: $ref: "#/components/schemas/Pet" responses: "200": description: Return a 200 status to indicate that the data was received successfully paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: "200": description: An paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" post: summary: Create a pet operationId: createPets tags: - pets responses: "201": description: Null response default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById tags: - pets parameters: - name: petId in: path required: true description: The id of the pet to retrieve schema: type: string responses: "200": description: Expected response to a valid request content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" components: schemas: Pet: required: - id - name properties: id: type: integer format: int64 name: type: - string - integer tag: type: string Pets: $id: test $anchor: test type: array items: $ref: "#/components/schemas/Pet" description: desc format: int32 Error: required: - code - message properties: code: type: integer format: int32 message: type: string ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/petstore-3.1_refs_siblings.yaml ================================================ openapi: "3.1.0" info: version: 1.0.0 title: Swagger Petstore summary: petstore sample for OAS 3.1.0 license: name: MIT identifier: test servers: - url: http://petstore.swagger.io/v1 paths: /ref_pet: $ref: "#/components/pathItems/pet" description: "ref pathItem description" summary: "ref pathItem summary" /pets: post: tags: - pets summary: Create a pet operationId: createPets parameters: - $ref: "#/components/parameters/testParameter" description: "ref parameter description" summary: "ref parameter summary" - name: randomParam in: query schema: type: string examples: refExample: $ref: "#/components/examples/testExample" description: "ref example description" summary: "ref example summary" callbacks: callIt: $ref: "#/components/callbacks/TestCallback" requestBody: $ref: "#/components/requestBodies/body" description: "ref request body description" summary: "ref request body summary" responses: "201": $ref: "#/components/responses/okResponse" description: "ref response description" summary: "ref response summary" default: description: 'default response' headers: head: $ref: "#/components/headers/head" description: "ref header description" summary: "ref header summary" components: schemas: Pet: required: - id - name properties: id: type: integer format: int64 name: type: string tag: type: string discriminator: propertyName: tag x-test-extension: extended Pets: type: array items: $ref: "#/components/schemas/Pet" description: desc format: int32 Error: required: - code - message properties: code: type: integer format: int32 message: type: string AnotherPet: title: Another Pet description: Another Pet for petstore referencing Pet schema $ref: "#/components/schemas/Pet" properties: category: type: string photoUrl: type: string pathItems: pet: description: get a pet get: operationId: getPet responses: "200": description: pet returned links: address: operationId: getUserAddressByUUID parameters: # get the `uuid` field from the `uuid` field in the response body userUuid: $response.body#/uuid callbacks: TestCallback: '{$request.query.queryUrl}': description: test path item post: operationId: testPathItem responses: default: description: ok securitySchemes: basic: $ref: "#/components/securitySchemes/http" http: type: http scheme: basic headers: head: schema: type: string requestBodies: body: description: client model content: application/json: schema: $ref: "#/components/schemas/Pet" responses: okResponse: description: everything is good" examples: testExample: value: Example on test parameters: testParameter: name: param in: query schema: type: string ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/petstore-3.1_sample.yaml ================================================ openapi: "3.1.0" info: version: 1.0.0 title: Swagger Petstore summary: petstore sample for OAS 3.1.0 license: name: MIT identifier: test servers: - url: http://petstore.swagger.io/v1 webhooks: # Each webhook needs a name newPet: # This is a Path Item Object, the only difference is that the request is initiated by the API provider post: requestBody: description: Information about a new pet in the system content: application/json: schema: $ref: "#/components/schemas/Pet" responses: "200": description: Return a 200 status to indicate that the data was received successfully paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: "200": description: An paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" post: summary: Create a pet operationId: createPets tags: - pets responses: "201": description: Null response default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById tags: - pets parameters: - name: petId in: path required: true description: The id of the pet to retrieve schema: type: string responses: "200": description: Expected response to a valid request content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" components: schemas: Pet: required: - id - name properties: id: type: integer format: int64 name: type: string tag: type: string discriminator: propertyName: tag x-test-extension: extended Pets: $id: test $anchor: test type: array items: $ref: "#/components/schemas/Pet" description: desc format: int32 Error: required: - code - message properties: code: type: integer format: int32 message: type: string responses: "201": description: api response description summary: api response summary parameters: param: in: query name: param0 description: parameter description summary: parameter summary schema: type: string examples: example: summary: example summary description: example description value: This is an example requestBodies: body: content: application/json: schema: { } headers: test-head: description: test header description summary: test header summary securitySchemes: basic: description: security description summary: security summary type: http links: Link: operationRef: "#/paths/~12.0~1repositories~1{username}/get" callbacks: TestCallback: '{$request.query.queryUrl}': description: test path item post: operationId: testPathItem pathItems: /pet: description: get a pet get: operationId: getPet responses: "200": description: pet returned ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/specWithDynamicRef.yaml ================================================ openapi: 3.1.0 info: title: Tree API version: 1.0.0 paths: /tree: post: summary: Create a tree structure requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ExtendedNode' responses: '200': description: Tree accepted content: application/json: schema: type: string components: schemas: BaseNode: $id: "https://example.com/schemas/base-node" $schema: "https://json-schema.org/draft/2020-12/schema" $dynamicAnchor: "node" type: object properties: name: type: string children: type: array items: $dynamicRef: "#node" required: [name] ExtendedProperties: $id: "https://example.com/schemas/extended-properties" $schema: "https://json-schema.org/draft/2020-12/schema" $dynamicAnchor: "node" type: object properties: type: type: string enum: [folder, file] required: [type] ExtendedNode: $schema: "https://json-schema.org/draft/2020-12/schema" $id: "https://example.com/schemas/extended-node" allOf: - $ref: "#/components/schemas/BaseNode" - $ref: "#/components/schemas/ExtendedProperties" ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/3.1.0/specWithReferredSchemas-3.1.yaml ================================================ openapi: 3.1.0 info: title: OpenAPI definition version: v0 servers: - url: http://localhost description: Generated server url paths: /users: get: summary: Get list of all users operationId: usersList responses: 200: description: OK content: application/json: schema: type: string maxLength: 100 minLength: 1 components: schemas: ResponseDefinition: properties: personalNumber: type: string WebhookResponseDefinition: properties: personalNumber: type: integer WebhookOperationDefinition: properties: personalNumber: type: number RequestBodyDefinition: properties: personalNumber: type: string ParameterDefinition: properties: parameterName: type: string HeaderDefinition: type: string description: header ref CallbackDefinition: description: callback ref type: string PathItemDefinition: description: pathItem ref type: string UnusedDefinition: description: unused definition type: string minLength: 1 maxLength: 100 responses: OK: description: OK content: application/json: schema: $ref: "#/components/schemas/ResponseDefinition" requestBodies: requestBody1: description: request body content: application/json: schema: $ref: "#/components/schemas/RequestBodyDefinition" parameters: parameter1: description: request body name: parameter in: query content: application/json: schema: $ref: "#/components/schemas/ParameterDefinition" headers: header1: content: application/json: schema: $ref: "#/components/schemas/HeaderDefinition" callbacks: myEvent: # Event name "{$request.body#/callbackUrl}": post: requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CallbackDefinition" pathItems: pathItem1: get: summary: Get list of all users operationId: usersList responses: 200: description: OK content: application/json: schema: $ref: "#/components/schemas/PathItemDefinition" webhooks: newPet: post: requestBody: description: Information about a new pet in the system content: application/json: schema: $ref: "#/components/schemas/WebhookOperationDefinition" description: Webhook Pet responses: '200': content: application/json: schema: $ref: "#/components/schemas/WebhookResponseDefinition" ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/additionalpropsmodel.json ================================================ { "swagger" : "2.0", "tags" : [ { "name" : "Test Api" } ], "paths" : { "/test" : { "get" : { "tags" : [ "Test Api" ], "operationId" : "getA", "parameters" : [ ], "responses" : { "200" : { "description" : "successful operation", "schema" : { "$ref" : "#/definitions/A" }, "headers" : { } } } } } }, "definitions" : { "A" : { "type" : "object", "properties" : { "id" : { "type" : "integer", "format" : "int32" }, "aggregates" : { "type" : "object", "additionalProperties" : { "$ref" : "#/definitions/B" } } } }, "B" : { "type" : "object", "properties" : { "id" : { "type" : "integer", "format" : "int32" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/brokenrefmodel.json ================================================ { "swagger" : "2.0", "tags" : [ { "name" : "Broken References Resource" } ], "paths" : { "/r/nested" : { "get" : { "tags" : [ "Broken References Resource" ], "operationId" : "getNestedModel", "parameters" : [ ], "responses" : { "200" : { "description" : "successful operation", "schema" : { "$ref" : "#/definitions/refname" }, "headers" : { } } } } }, "/r/root" : { "get" : { "tags" : [ "Broken References Resource" ], "operationId" : "getRootModel", "parameters" : [ ], "responses" : { "200" : { "description" : "successful operation", "schema" : { "$ref" : "#/definitions/RootModel" }, "headers" : { } } } } } }, "definitions" : { "RootModel" : { "type" : "object", "properties" : { "nested" : { "$ref" : "#/definitions/refname" } } }, "NestedModel" : { "type" : "object" } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/compositionTest-3.0.json ================================================ { "openapi": "3.0.1", "info": { "version": "1.0.0", "license": { "name": "MIT" }, "title": "Swagger Petstore" }, "servers": [ { "url": "http://petstore.swagger.io/v1" } ], "paths": {}, "components": { "schemas": { "Pet": { "discriminator": { "propertyName": "pet_type", "mapping": { "cachorro": "#/components/schemas/Dog" } }, "required": [ "pet_type" ], "type": "object", "properties": { "pet_type": { "type": "string" } } }, "Lizard": { "allOf": [ { "$ref": "#/components/schemas/Pet" }, { "type": "object", "properties": { "lovesRocks": { "type": "boolean" } } } ] }, "Dog": { "allOf": [ { "$ref": "#/components/schemas/Pet" }, { "type": "object", "properties": { "bark": { "type": "string" } } } ] }, "Cat": { "allOf": [ { "$ref": "#/components/schemas/Pet" }, { "type": "object", "properties": { "name": { "type": "string" } } } ] } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/compositionTest.json ================================================ { "swagger": 2.0, "info": { "description": "This is a sample server Petstore server. You can find out more about Swagger at http://swagger.io or on irc.freenode.net, #swagger. For this sample, you can use the api key \"special-key\" to test the authorization filters", "version": "1.0.0", "title": "Swagger Petstore", "termsOfService": "http://swagger.io/terms/", "contact": { "name": "apiteam@swagger.io" }, "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.html" } }, "basePath": "petstore.swagger.io:80/api", "paths": {}, "definitions": { "Pet": { "allOf": [ { "$ref": "Human" }, { "$ref": "Animal" }, { "$ref": "Bird" }, { "properties": { "isDomestic": { "type": "boolean" } } } ] }, "Human": { "required": [ "name" ], "properties": { "name": { "type": "string", "description": "The name of the human" }, "type": { "type": "string" }, "firstName": { "type": "string" }, "lastName": { "type": "string" } }, "discriminator": "type" }, "Animal": { "required": [ "hasLegs" ], "properties": { "hasLegs": { "type": "boolean" } }, "discriminator": "hasLegs" }, "Bird": { "required": [ "hasWings" ], "properties": { "hasWings": { "type": "boolean" } }, "discriminator": "hasWings" } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/deprecatedoperationmodel.json ================================================ { "openapi": "3.0.1", "tags" : [ { "name" : "Test Api" } ], "paths" : { "/test" : { "get" : { "tags" : [ "Test Api" ], "operationId" : "getA", "parameters" : [ ], "responses" : { "200" : { "description" : "successful operation", "schema" : { "$ref" : "#/definitions/EmptyModel" }, "headers" : { } } }, "deprecated" : true } } }, "components" : { "EmptyModel" : { "type" : "object" } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/jsonSerialization-expected-petstore-3.0.json ================================================ { "openapi": "3.0.1", "info": { "title": "Swagger Petstore", "license": { "name": "MIT" }, "version": "1.0.0" }, "servers": [ { "url": "http://petstore.swagger.io/v1" } ], "paths": { "/pets": { "get": { "tags": [ "pets" ], "summary": "List all pets", "operationId": "listPets", "parameters": [ { "name": "limit", "in": "query", "description": "How many items to return at one time (max 100)", "required": false, "schema": { "type": "integer", "format": "int32" } } ], "responses": { "200": { "description": "An paged array of pets", "headers": { "x-next": { "description": "A link to the next page of responses", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pets" } } } }, "default": { "description": "unexpected error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "post": { "tags": [ "pets" ], "summary": "Create a pet", "operationId": "createPets", "responses": { "201": { "description": "Null response" }, "default": { "description": "unexpected error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/pets/{petId}": { "get": { "tags": [ "pets" ], "summary": "Info for a specific pet", "operationId": "showPetById", "parameters": [ { "name": "petId", "in": "path", "description": "The id of the pet to retrieve", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Expected response to a valid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pets" } } } }, "default": { "description": "unexpected error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } }, "components": { "schemas": { "Pet": { "required": [ "id", "name" ], "type": "object", "properties": { "tag": { "type": "string" }, "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } } }, "Pets": { "type": "array", "items": { "$ref": "#/components/schemas/Pet" } }, "Error": { "required": [ "code", "message" ], "type": "object", "properties": { "message": { "type": "string" }, "code": { "type": "integer", "format": "int32" } } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/media-type-null-example.yaml ================================================ openapi: "3.0.1" info: version: 1.0.0 title: Swagger Petstore license: name: MIT servers: - url: https://petstore3.swagger.io/api/v3 paths: /pet: post: tags: - pet summary: Add a new pet to the store operationId: addPet requestBody: description: Pet object that needs to be added to the store content: application/json: schema: $ref: "#/components/schemas/Pet" example: id: 10 name: kitty tag: something required: true responses: 200: description: Expected response to a valid request content: application/json: schema: $ref: "#/components/schemas/Pet" /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById tags: - pets parameters: - name: petId in: path required: true description: The id of the pet to retrieve schema: type: string responses: 200: description: Expected response to a valid request content: application/json: schema: $ref: "#/components/schemas/Pet" example: null components: schemas: Pet: required: - id - name properties: id: type: integer format: int64 name: type: string tag: type: string ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/noModels.json ================================================ { "swagger": "2.0", "info": { "description": "This is a sample server Petstore server. You can find out more about Swagger at http://swagger.io or on irc.freenode.net, #swagger. For this sample, you can use the api key \"special-key\" to test the authorization filters", "version": "1.0.0", "title": "Swagger Petstore", "termsOfService": "http://swagger.io/terms/", "contact": { "email": "apiteam@swagger.io" }, "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.html" } }, "host": "localhost:8002", "basePath": "/api", "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "store", "description": "Access to Petstore orders" }, { "name": "user", "description": "Operations about user", "externalDocs": { "description": "Find out more about our store", "url": "http://swagger.io" } } ], "schemes": [ "http" ], "paths": { "/pet": { "post": { "operationId": "addPet", "parameters": [], "responses": { "default": { "description": "successful operation" } } }, "put": { "operationId": "updatePet", "parameters": [], "responses": { "default": { "description": "successful operation" } } } }, "/pet/findByStatus": { "get": { "operationId": "findPetsByStatus", "parameters": [ { "name": "status", "in": "query", "required": false, "type": "string" } ], "responses": { "default": { "description": "successful operation" } } } }, "/pet/findByTags": { "get": { "operationId": "findPetsByTags", "parameters": [ { "name": "tags", "in": "query", "required": false, "type": "string" } ], "responses": { "default": { "description": "successful operation" } } } }, "/pet/{petId}": { "get": { "operationId": "getPetById", "parameters": [ { "name": "petId", "in": "path", "required": true, "type": "string" } ], "responses": { "default": { "description": "successful operation" } } } }, "/store/order": { "post": { "operationId": "placeOrder", "parameters": [], "responses": { "default": { "description": "successful operation" } } } }, "/store/order/{orderId}": { "get": { "operationId": "getOrderById", "parameters": [ { "name": "orderId", "in": "path", "required": true, "type": "string" } ], "responses": { "default": { "description": "successful operation" } } }, "delete": { "operationId": "deleteOrder", "parameters": [ { "name": "orderId", "in": "path", "required": true, "type": "string" } ], "responses": { "default": { "description": "successful operation" } } } }, "/user": { "post": { "operationId": "createUser", "parameters": [], "responses": { "default": { "description": "successful operation" } } } }, "/user/createWithArray": { "post": { "operationId": "createUsersWithArrayInput", "parameters": [], "responses": { "default": { "description": "successful operation" } } } }, "/user/createWithList": { "post": { "operationId": "createUsersWithListInput", "parameters": [], "responses": { "default": { "description": "successful operation" } } } }, "/user/login": { "get": { "operationId": "loginUser", "parameters": [ { "name": "username", "in": "query", "required": false, "type": "string" }, { "name": "password", "in": "query", "required": false, "type": "string" } ], "responses": { "default": { "description": "successful operation" } } } }, "/user/logout": { "get": { "operationId": "logoutUser", "parameters": [], "responses": { "default": { "description": "successful operation" } } } }, "/user/{username}": { "get": { "operationId": "getUserByName", "parameters": [ { "name": "username", "in": "path", "required": true, "type": "string" } ], "responses": { "default": { "description": "successful operation" } } }, "put": { "operationId": "updateUser", "parameters": [ { "name": "username", "in": "path", "required": true, "type": "string" } ], "responses": { "default": { "description": "successful operation" } } }, "delete": { "operationId": "deleteUser", "parameters": [], "responses": { "default": { "description": "successful operation" } } } } }, "securityDefinitions": { "api_key": { "type": "apiKey", "name": "api_key", "in": "header" }, "petstore_auth": { "type": "oauth2", "authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog", "flow": "implicit", "scopes": { "write:pets": "modify pets in your account", "read:pets": "read your pets" } } }, "externalDocs": { "description": "Find out more about Swagger", "url": "http://swagger.io" } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/null-example.yaml ================================================ openapi: 3.0.2 info: title: VirtServer support for null examples version: 1.0.0 paths: /object-with-null-example: get: description: Response should be `null` responses: '200': description: Should be `null` content: application/json: schema: $ref: "#/components/schemas/ObjectWithNullExample" /object-with-null-in-schema-example: get: description: 'Response should be `{..., "d": null}`' responses: '200': description: 'Should be `{..., "d": null}`' content: application/json: schema: $ref: "#/components/schemas/ObjectWithNullInSchemaExample" /object-with-null-property-example: get: description: 'Response should be `{"a": 5, "b": null}`' responses: '200': description: 'Should be `{"a": 5, "b": null}`' content: application/json: schema: $ref: "#/components/schemas/ObjectWithNullPropertyExample" /string-with-null-example: get: description: Response should be `null` responses: '200': description: Should be `null` content: application/json: schema: $ref: "#/components/schemas/StringWithNullExample" /array-with-null-array-example: get: description: Response should be `null` responses: '200': description: Should be `null` content: application/json: schema: $ref: "#/components/schemas/ArrayWithNullArrayExample" /array-with-null-item-example: get: description: Response should be `[null]` responses: '200': description: Should be `[null]` content: application/json: schema: $ref: "#/components/schemas/ArrayWithNullItemExample" /arrey-with-null-in-array-example: get: description: Response should be `["foo", null]` responses: '200': description: Should be `["foo", null]` content: application/json: schema: $ref: "#/components/schemas/ArrayWithNullInArrayExample" /object-without-null-example: get: description: Response should be `null` responses: '200': description: Should be `null` content: application/json: schema: $ref: "#/components/schemas/ObjectWithoutNullExample" /object-without-null-in-schema-example: get: description: 'Response should be `{..., "d": null}`' responses: '200': description: 'Should be `{..., "d": null}`' content: application/json: schema: $ref: "#/components/schemas/ObjectWithoutNullInSchemaExample" /object-without-null-property-example: get: description: 'Response should be `{"a": 5, "b": null}`' responses: '200': description: 'Should be `{"a": 5, "b": null}`' content: application/json: schema: $ref: "#/components/schemas/ObjectWithoutNullPropertyExample" /string-without-null-example: get: description: Response should be `null` responses: '200': description: Should be `null` content: application/json: schema: $ref: "#/components/schemas/StringWithoutNullExample" /array-without-null-array-example: get: description: Response should be `null` responses: '200': description: Should be `null` content: application/json: schema: $ref: "#/components/schemas/ArrayWithoutNullArrayExample" /array-without-null-item-example: get: description: Response should be `[null]` responses: '200': description: Should be `[null]` content: application/json: schema: $ref: "#/components/schemas/ArrayWithoutNullItemExample" /arrey-without-null-in-array-example: get: description: Response should be `["foo", null]` responses: '200': description: Should be `["foo", null]` content: application/json: schema: $ref: "#/components/schemas/ArrayWithoutNullInArrayExample" components: schemas: ObjectWithNullExample: type: object properties: foo: type: string nullable: true example: null ObjectWithNullInSchemaExample: type: object example: a: 5 b: test c: true d: null ObjectWithNullPropertyExample: type: object properties: a: type: integer example: 5 b: type: string nullable: true example: null StringWithNullExample: type: string nullable: true example: null ArrayWithNullArrayExample: type: array items: type: string nullable: true example: null ArrayWithNullItemExample: type: array items: type: string nullable: true example: null ArrayWithNullInArrayExample: type: array items: type: string nullable: true example: [foo, null] ObjectWithoutNullExample: type: object properties: foo: type: string nullable: true ObjectWithoutNullInSchemaExample: type: object example: a: 5 b: test c: true ObjectWithoutNullPropertyExample: type: object properties: a: type: integer example: 5 b: type: string nullable: true StringWithoutNullExample: type: string nullable: true ArrayWithoutNullArrayExample: type: array items: type: string nullable: true ArrayWithoutNullItemExample: type: array items: type: string nullable: true ArrayWithoutNullInArrayExample: type: array items: type: string nullable: true example: [foo] ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/null-in-schema-example.yaml ================================================ openapi: 3.0.2 info: title: VirtServer support for null examples version: 1.0.0 paths: /object-with-null-in-schema-example: get: description: 'Response should be `{..., "d": null}`' responses: '200': description: 'Should be `{..., "d": null}`' content: application/json: schema: $ref: "#/components/schemas/ObjectWithNullInSchemaExample" components: schemas: ObjectWithNullInSchemaExample: type: object example: a: 5 b: test c: true d: null ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/oas3.yaml ================================================ --- openapi: 3.0.1 servers: - url: http://petstore.swagger.io/v2 - url: https://development.gigantic-server.com/v1 description: Development server - url: https://{username}.gigantic-server.com:{port}/{basePath} x-server: server extension description: The production API server variables: username: # note! no enum here means it is an open value default: demo description: this value is assigned by the service provider, in this example `gigantic-server.com` port: enum: - 8443 - 443 default: 8443 basePath: # open meaning there is the opportunity to use special base paths as assigned by the provider, default is `v2` default: v2 description: testing overwriting enum: - 2222 - 333 x-origin: - url: http://petstore.swagger.io/v2/swagger.json format: swagger version: '2.0' converter: url: https://github.com/mermade/swagger2openapi version: 1.2.1 x-api-title: pet store test api security: - api_key: [] - tokenAuth: [] info: description: 'This is a sample server Petstore' title: Sample Pet Store App termsOfService: http://swagger.io/terms/ x-info: info extension contact: name: API Support url: http://www.example.com/support email: support@example.com x-contact: contact extension license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html x-license: license extension version: 1.0.1 tags: - name: pet description: Everything about your Pets externalDocs: description: Find out more url: http://swagger.io - name: store description: Access to Petstore orders - name: user description: Operations about user externalDocs: description: Find out more about our store url: http://swagger.io paths: "/pathItemRef": "$ref": 'http://localhost:${dynamicPort}/remote/path' "/pathItemRef2": "$ref": "#/paths/~1pet" "/pet": summary: summary description: description post: externalDocs: description: Find out more url: http://swagger.io tags: - pet summary: Add a new pet to the store description: '' operationId: addPet parameters: [] responses: '405': description: Invalid input headers: X-Rate-Limit: description: calls per hour allowed by the user schema: title: header schema type: integer format: int32 X-Expires-After: description: date in UTC when token expires schema: type: string format: date-time security: - petstore_auth: - write:pets - read:pets requestBody: "$ref": "#/components/requestBodies/requestBody1" description: user to add to the system required: true content: 'application/json': schema: $ref: "#/components/schemas/User" examples: user: summary: User Example externalValue: 'http://foo.bar/examples/user-example.json' 'application/xml': schema: $ref: "#/components/schemas/User" examples: user: summary: User Example in XML externalValue: 'http://foo.bar/examples/user-example.xml' 'text/plain': examples: user: summary: User example in text plain format externalValue: 'http://foo.bar/examples/user-example.txt' '*/*': examples: user: summary: User example in other format externalValue: 'http://foo.bar/examples/user-example.whatever' servers: - url: http://petstore.swagger.io/v2 parameters: - name: status in: query description: Status values that need to be considered for filter required: true schema: type: array items: type: string enum: - available - pending - sold default: available - "$ref": "#/components/parameters/skipParam" put: tags: - pet summary: Update an existing pet description: '' operationId: updatePet parameters: [] responses: '400': description: A complex object array response content: application/json: schema: type: array items: $ref: "#/components/schemas/VeryComplexType" '404': description: Pet not found '405': description: Validation exception security: - petstore_auth: - write:pets - read:pets requestBody: "$ref": "#/components/requestBodies/requestBody1" "/pet/findByStatus": get: tags: - pet summary: Finds Pets by status description: Multiple status values can be provided with comma separated strings operationId: findPetsByStatus parameters: - name: status in: query description: Status values that need to be considered for filter required: true example: "example" schema: title: title test format: int64 minimum: 1 maximum: 10 allOf: - $ref: "#/components/schemas/Pet" - type: object properties: huntingSkill: type: string description: The measured skill for hunting enum: - clueless - lazy - adventurous - aggressive xml: namespace: http://example.com/schema/sample prefix: sample enum: - available - pending - sold type: object properties: id: type: integer format: int64 name: type: string xml: namespace: http://inside/properties/schema prefix: inside properties schema required: - name - pet example: name: Puma id: 1 externalDocs: description: External Docs Inside Schema url: http://swagger.io inside Schema items: type: string enum: - available - pending - sold default: available content: 'application/json': schema: type: array items: type: string example: example string examples: list: summary: List of Names value: - Bob - Diane - Mary - Bill empty: summary: Empty value: {} encoding: historyMetadata: # require XML Content-Type in utf-8 encoding contentType: application/xml; charset=utf-8 profileImage: # only accept png/jpeg contentType: image/png, image/jpeg headers: X-Rate-Limit: description: calls per hour allowed by the user schema: type: integer format: int32 'application/xml': examples: list: summary: List of names value: "" empty: summary: Empty list value: "" 'text/plain': examples: list: summary: List of names value: "Bob,Diane,Mary,Bill" empty: summary: Empty value: "" responses: '200': description: successful operation content: application/xml: schema: type: array items: "$ref": "#/components/schemas/Pet" application/json: schema: type: array items: "$ref": "#/components/schemas/Pet" '400': description: Invalid status value security: - petstore_auth: - write:pets - read:pets requestBody: description: pet store to add to the system required: true content: multipart/mixed: schema: type: object properties: id: # default is text/plain type: string format: uuid address: # default is application/json type: object properties: {} historyMetadata: # need to declare XML format! description: metadata in XML format type: object properties: {} profileImage: # default is application/octet-stream, need to declare an image type only! type: string format: binary encoding: historyMetadata: # require XML Content-Type in utf-8 encoding contentType: application/xml; charset=utf-8 profileImage: # only accept png/jpeg contentType: image/png, image/jpeg headers: X-Rate-Limit: description: calls per hour allowed by the user schema: type: integer format: int32 X-Expires-After: description: date in UTC when token expires schema: type: string format: date-time callbacks: mainHook: '$request.body#/url': post: responses: '200': description: webhook successfully processed operation "/pet/findByTags": get: tags: - pet summary: Finds Pets by tags description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. operationId: findPetsByTags parameters: - name: tags in: query description: Tags to filter by required: true schema: type: array items: type: string responses: '200': description: successful operation content: application/xml: schema: type: array items: "$ref": "#/components/schemas/Pet" application/json: schema: type: array items: "$ref": "#/components/schemas/Pet" '400': description: Invalid tag value callbacks: mainHook: '$ref': "#/components/callbacks/failed" security: - petstore_auth: - write:pets - read:pets deprecated: true "/pet/{petId}": get: tags: - pet summary: Find pet by ID description: Returns a single pet operationId: getPetById parameters: - name: petId in: path description: ID of pet to return required: true schema: type: integer format: int64 responses: '200': description: successful operation content: application/xml: schema: "$ref": "#/components/schemas/Pet" application/json: schema: "$ref": "#/components/schemas/Pet" '400': description: Invalid ID supplied '404': description: Pet not found callbacks: mainHook: '$request.body#/url': post: responses: '200': description: successful operation content: application/xml: schema: "$ref": "#/components/schemas/Pet" security: - api_key: [] post: tags: - pet summary: Updates a pet in the store with form data description: '' operationId: updatePetWithForm parameters: - name: petId in: path description: ID of pet that needs to be updated required: true schema: type: integer format: int64 responses: '405': description: Invalid input security: - petstore_auth: - write:pets - read:pets requestBody: content: application/x-www-form-urlencoded: schema: type: object properties: name: description: Updated name of the pet type: string required: false status: description: Updated status of the pet type: string required: false delete: tags: - pet summary: Deletes a pet description: '' operationId: deletePet parameters: - name: api_key in: header required: false schema: type: string - name: petId in: path description: Pet id to delete required: true schema: type: integer format: int64 responses: '400': description: Invalid ID supplied '404': description: Pet not found security: - petstore_auth: - write:pets - read:pets "/pet/{petId}/uploadImage": post: tags: - pet summary: uploads an image description: '' operationId: uploadFile parameters: - name: petId in: path description: ID of pet to update required: true schema: type: integer format: int64 responses: '200': description: successful operation content: application/json: schema: "$ref": "#/components/schemas/ApiResponse" security: - petstore_auth: - write:pets - read:pets requestBody: content: application/octet-stream: schema: type: string format: binary "/store/inventory": get: tags: - store summary: Returns pet inventories by status description: Returns a map of status codes to quantities operationId: getInventory parameters: [] responses: '200': description: successful operation content: application/json: schema: type: object additionalProperties: type: integer format: int32 security: - api_key: [] "/store/order": post: tags: - store summary: Place an order for a pet description: '' operationId: placeOrder parameters: [] responses: '200': description: successful operation content: application/xml: schema: "$ref": "#/components/schemas/Order" application/json: schema: "$ref": "#/components/schemas/Order" '400': description: Invalid Order requestBody: content: application/json: description: order placed for purchasing the pet schema: "$ref": "#/components/schemas/Order" "/store/order/{orderId}": get: tags: - store summary: Find purchase order by ID description: For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions operationId: getOrderById parameters: - name: orderId in: path description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 minimum: 1 maximum: 10 responses: '200': description: successful operation content: application/xml: schema: "$ref": "#/components/schemas/Order" application/json: schema: "$ref": "#/components/schemas/Order" '400': description: Invalid ID supplied '404': description: Order not found delete: tags: - store summary: Delete purchase order by ID description: For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors operationId: deleteOrder parameters: - name: orderId in: path description: ID of the order that needs to be deleted required: true schema: type: integer format: int64 minimum: 1 responses: '400': description: Invalid ID supplied '404': description: Order not found "/user": post: tags: - user summary: Create user description: This can only be done by the logged in user. operationId: createUser parameters: [] responses: default: description: successful operation requestBody: content: application/json: description: Created user object schema: "$ref": "#/components/schemas/User" "/user/createWithArray": post: tags: - user summary: Creates list of users with given input array description: '' operationId: createUsersWithArrayInput parameters: [] responses: default: description: successful operation requestBody: "$ref": "#/components/requestBodies/requestBody2" "/user/createWithList": post: tags: - user summary: Creates list of users with given input array description: '' operationId: createUsersWithListInput parameters: [] responses: default: description: successful operation requestBody: "$ref": "#/components/requestBodies/requestBody2" "/user/login": get: tags: - user summary: Logs user into the system description: '' operationId: loginUser parameters: - name: username in: query description: The user name for login required: true schema: type: string - name: password in: query description: The password for login in clear text required: true schema: type: string format: password responses: '200': description: successful operation headers: X-Rate-Limit: description: calls per hour allowed by the user schema: type: integer format: int32 X-Expires-After: description: date in UTC when token expires schema: type: string format: date-time content: application/xml: schema: type: string application/json: schema: type: string '400': description: Invalid username/password supplied "/user/logout": get: tags: - user summary: Logs out current logged in user session description: '' operationId: logoutUser parameters: [] responses: default: description: successful operation "/user/{username}": get: tags: - user summary: Get user by user name description: '' operationId: getUserByName parameters: - name: username in: path description: 'The name that needs to be fetched. Use user1 for testing. ' required: true schema: type: string responses: '200': description: successful operation content: application/xml: schema: "$ref": "#/components/schemas/User" application/json: schema: "$ref": "#/components/schemas/User" '400': description: Invalid username supplied '404': description: User not found put: tags: - user summary: Updated user description: This can only be done by the logged in user. operationId: updateUser parameters: - name: username in: path description: name that need to be updated required: true schema: type: string responses: '400': description: Invalid user supplied '404': description: User not found requestBody: content: application/json: description: Updated user object schema: "$ref": "#/components/schemas/User" delete: tags: - user summary: Delete user description: This can only be done by the logged in user. operationId: deleteUser parameters: - name: username in: path description: The name that needs to be deleted required: true schema: type: string responses: '400': description: Invalid username supplied '404': description: User not found externalDocs: description: Find out more about Swagger url: http://swagger.io components: schemas: VeryComplexType: type: integer format: int32 ExtendedErrorModel: allOf: - type: object required: - rootCause properties: rootCause: type: string "$ref": "#/components/schemas/Category" Order: type: object not: type: integer format: int32 additionalProperties: type: integer properties: id: type: integer format: int64 petId: type: integer format: int64 quantity: type: integer format: int32 shipDate: type: string format: date-time status: type: string description: Order Status enum: - placed - approved - delivered complete: type: boolean default: false xml: name: Order OrderRef: type: object not: type: integer format: int32 "$ref": "#/components/schemas/Category" additionalProperties: type: integer "$ref": "http://localhost:${dynamicPort}/remote/schema#/components/schemas/User" properties: id: type: integer format: int64 petId: type: integer format: int64 quantity: type: integer format: int32 shipDate: type: string format: date-time status: type: string description: Order Status enum: - placed - approved - delivered complete: type: boolean default: false xml: name: Order Category: type: object properties: id: type: integer format: int64 name: type: string xml: name: Category User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer format: int32 description: User Status xml: name: User Tag: type: object properties: id: type: integer format: int64 name: type: string xml: name: Tag Pet: type: object required: - name - photoUrls properties: id: type: integer format: int64 category: "$ref": "#/components/schemas/Category" user: type: string example: doggie "$ref": "http://localhost:${dynamicPort}/remote/schema#/components/schemas/User" photoUrls: type: array xml: name: photoUrl wrapped: true items: type: string tags: type: array xml: name: tag wrapped: true items: "$ref": "#/components/schemas/Tag" status: type: string description: pet status in the store enum: - available - pending - sold xml: name: Pet ApiResponse: type: object required: - name - photoUrls properties: code: type: integer format: int32 type: type: string message: type: string responses: Found: description: Entity not found. "$ref": "http://localhost:${dynamicPort}/remote/response#/responses/NotFound" NotFound: description: Entity not found. IllegalInput: description: Illegal input for operation. GeneralError: description: General Error content: application/json: schema: $ref: "#/components/schemas/ExtendedErrorModel" parameters: refParam: "$ref": "#/components/parameters/limitParam/" newParam: name: skip in: query description: number of items to skip required: true schema: type: integer format: int32 "$ref": "#/components/schemas/Tag" skipParam: name: skip in: query description: number of items to skip required: true schema: type: integer format: int32 limitParam: name: limit in: query description: max records to return required: true schema: type: integer format: int32 examples: cat: summary: An example of a cat value: name: Fluffy petType: Cat color: White gender: male breed: Persian dog: summary: An example of a dog with a cat's name value: name: Puma petType: Dog color: Black gender: Female breed: Mixed frog: $ref: "#/components/examples/cat" requestBodies: requestBody1: description: request body in components content: application/json: description: Pet object that needs to be added to the store schema: "$ref": "#/components/schemas/Pet" application/xml: description: Pet object that needs to be added to the store schema: "$ref": "#/components/schemas/Pet" requestBody2: content: application/json: description: List of user object schema: type: array items: "$ref": "#/components/schemas/User" requestBody3: "$ref": "#/components/requestBodies/requestBody2" securitySchemes: reference: "$ref": "#/components/securitySchemes/api_key" petstore_auth: type: oauth2 flows: implicit: authorizationUrl: http://petstore.swagger.io/oauth/dialog scopes: write:pets: modify pets in your account read:pets: read your pets api_key: type: apiKey name: api_key in: header headers: X-Ref-Limit-Limit: "$ref": "#/components/headers/X-Rate-Limit-Reset" X-Rate-Limit-Limit: description: The number of allowed requests in the current period schema: type: integer example: "This is a header example" X-Rate-Limit-Remaining: description: The number of remaining requests in the current period schema: type: integer "$ref": "http://localhost:${dynamicPort}/remote/schema#/components/schemas/User" X-Rate-Limit-Reset: description: The number of seconds left in the current period schema: type: integer links: referenced: "$ref": "#/components/links/unsubscribe" unsubscribe: operationId: cancelHookCallback parameters: id: $response.body#/hookId x-link: link extension callbacks: referenced: "$ref": "#/components/callbacks/failed" heartbeat: '$request.query.heartbeat-url': post: requestBody: $ref: "#/components/requestBodies/requestBody3" responses: '200': description: Consumer acknowledged the callback failed: '$response.body#/failedUrl': post: requestBody: $ref: "#/components/requestBodies/requestBody3" responses: '200': description: Consumer acknowledged the callback failed success: '$response.body#/successUrl': post: requestBody: $ref: "#/components/requestBodies/requestBody1" responses: '200': description: Consumer acknowledged the callback x-component: - url: http://component.swagger.io/v2/swagger.json format: OAS version: '3.0' converter: url: https://github.com/mermade/oas3 version: 1.2.3 x-api-title: pet store test api in components ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/oas3_2.yaml ================================================ openapi: 3.0.0 servers: - url: http://petstore.swagger.io/api - url: https://development.gigantic-server.com/api description: Development server - url: https://{username}.gigantic-server.com:{port}/{basePath} x-server: server extension description: The production API server variables: username: # note! no enum here means it is an open value default: demo description: this value is assigned by the service provider, in this example `gigantic-server.com` port: enum: - 8443 - 443 default: 8443 basePath: # open meaning there is the opportunity to use special base paths as assigned by the provider, default is `v2` default: v2 description: testing overwriting enum: - 2222 - 333 x-origin: - url: http://petstore.swagger.io/v2/swagger.json format: swagger version: '2.0' converter: url: https://github.com/mermade/swagger2openapi version: 1.2.1 x-api-title: pet store test api security: - api_key: [] - tokenAuth: [] info: description: 'This is a sample server Petstore' version: 1.0.0 title: testing source file termsOfService: http://swagger.io/terms/ x-info: info extension contact: name: API Support url: http://www.example.com/support email: support@example.com x-contact: contact extension license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html x-license: license extension tags: - name: pet description: Everything about your Pets externalDocs: description: Find out more url: http://swagger.io - name: store description: Access to Petstore orders - name: user description: Operations about user externalDocs: description: Find out more about our store url: http://swagger.io paths: "/pet": summary: summary description: description post: x-swagger-router-controller: TestController externalDocs: description: Find out more url: http://swagger.io tags: - pet summary: Add a new pet to the store description: '' operationId: addPet parameters: [] responses: '200': description: party time! content: "application/json": schema: "$ref": "#/components/schemas/Dog" '405': description: Invalid input headers: X-Rate-Limit: description: calls per hour allowed by the user schema: title: header schema type: integer format: int32 X-Expires-After: description: date in UTC when token expires schema: type: string format: date-time security: - petstore_auth: - write:pets - read:pets requestBody: description: user to add to the system required: true content: 'application/json': schema: $ref: "#/components/schemas/Dog" servers: - url: http://petstore.swagger.io/v2 put: tags: - pet summary: Update an existing pet description: '' operationId: updatePet parameters: [] responses: '400': description: A complex object array response content: application/json: schema: type: array items: $ref: "#/components/schemas/VeryComplexType" '404': description: Pet not found '405': description: Validation exception security: - petstore_auth: - write:pets - read:pets requestBody: "$ref": "#/components/requestBodies/requestBody1" "/producesTest": get: parameters: [] responses: '200': description: it works content: application/json: schema: type: object properties: name: type: string "/fileUpload": post: x-swagger-router-controller: TestController operationId: uploadFile requestBody: content: multipart/form-data: schema: properties: theFile: type: string format: binary stringMetadata: type: string intMetadata: type: integer format: int32 responses: '200': description: the stringMetadata passed in content: "*/*": schema: type: string "/primitiveBody/inline": post: x-swagger-router-controller: TestController operationId: inlineRequiredBody requestBody: content: "application/json": schema: type: object properties: name: type: string required: true responses: '200': description: ok! "/primitiveBody/string": post: x-swagger-router-controller: TestController operationId: stringBody requestBody: content: "application/yaml": schema: type: string required: false responses: '200': description: ok! "/primitiveBody/integer": post: x-swagger-router-controller: TestController operationId: integerBody requestBody: content: "*/*": schema: type: integer format: int32 required: false responses: '200': description: ok! "/primitiveBody/binary": post: x-swagger-router-controller: TestController operationId: binaryBody requestBody: content: application/octet-stream: schema: type: string format: binary required: false responses: '200': description: ok! content: application/octet-stream: schema: type: string format: binary "/hidden": get: x-inflector-hidden: true responses: default: description: ok "/arrayInputTest": get: x-swagger-router-controller: TestController operationId: arrayInputTest tags: - inputTest parameters: - name: users in: query required: true style: form schema: type: array items: type: string responses: '200': description: success! "/formTest": post: operationId: formTest x-swagger-router-controller: TestController requestBody: content: x-www-form-urlencoded: schema: properties: user: type: string responses: '200': description: success! "/mockResponses": get: tags: - mockResponses parameters: - name: user in: query required: true schema: type: string responses: '200': description: success! "/mockResponses/primitiveFloatResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: number format: float "/mockResponses/primitiveDoubleResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: number format: double "/mockResponses/primitiveStringResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: string "/mockResponses/primitiveStringResponseWithExample": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: string example: fun "/mockResponses/responseWithExamples": get: tags: - mockResponses responses: '200': description: success! content: application/json: examples: application/json: value: {"test":"jsonvalue"} application/yaml: examples: application/yaml: value: test: yamlvalue "/mockResponses/primitiveDateResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: string format: date "/mockResponses/primitiveDateTimeResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: string format: date-time "/mockResponses/primitiveBigDecimalResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: number "/mockResponses/primitiveEmailResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: string format: email "/mockResponses/primitiveUUIDResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: string format: uuid "/mockResponses/primitiaveMapResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: object additionalProperties: type: string "/mockResponses/complexResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: "$ref": "#/components/schemas/Address" "/mockResponses/complexResponseWithExample": get: tags: - mockResponses responses: '200': description: success! content: application/json: schema: "$ref": "#/components/schemas/User" "/mockResponses/complexArrayResponse": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: array items: "$ref": "#/components/schemas/Address" "/mockResponses/complexArrayResponseWithExample": get: tags: - mockResponses parameters: - name: user in: query required: false schema: type: string responses: '200': description: success! content: application/json: schema: type: array items: $ref: "#/components/schemas/User" "/issue-125": get: parameters: [] responses: '200': description: int16 content: "*/*": schema: type: integer format: int16 "/issue-128": get: responses: '303': description: issue 128 content: "application/json": schema: type: string format: url example: http://foo.bar/other "/issue-130": get: responses: '200': description: issue 130 content: "application/json": schema: type: object description: an object with array properties properties: aStringArray: type: array items: type: string example: a string value anIntegerArray: type: array items: type: integer format: int32 example: 99 "/issue-132": get: responses: '303': description: issue 132 headers: Location: schema: type: string format: url example: 'http://foo.bar/other' description: URI of the entity affected by the property change "/issue-132.2": get: responses: '303': description: issue 133, alternate example headers: _links: description: array of locations schema: type: array items: type: string format: url example: 'http://foo.bar/other' "/form": post: x-swagger-router-controller: TestController operationId: postFormData requestBody: content: {} responses: '200': description: ok "/goodbye": get: operationId: goodbye x-swagger-router-controller: TestController parameters: - name: happy in: query required: true style: form schema: type: array items: type: string responses: '200': description: success! content: application/json: schema: "$ref": "#/components/schemas/User" "/hello": get: tags: - test1 operationId: testMe parameters: - name: limit in: query required: true schema: minimum: 0 type: integer format: int32 - name: min in: query required: true schema: minimum: 10 type: integer format: int32 responses: '200': description: fun! content: application/json: schema: type: string "/withModelArray/{id}": post: operationId: withModelArray x-swagger-router-controller: TestController parameters: - name: id in: path required: true schema: type: string requestBody: content: application/json: schema: type: array items: $ref: "#/components/schemas/Address" required: true responses: '200': description: success! content: "application/json": schema: "$ref": "#/components/schemas/Animal" "/withModel/{id}": get: tags: - test2 operationId: withModel x-swagger-router-controller: TestController parameters: - name: id in: path required: true schema: type: string responses: '200': description: success! content: "*/*": schema: "$ref": "#/components/schemas/Animal" post: tags: - test2 operationId: withModel x-swagger-router-controller: TestController parameters: - name: id in: path required: true schema: type: string requestBody: content: "*/*": schema: "$ref": "#/components/schemas/Address" required: false responses: '200': description: success! content: "*/*": schema: "$ref": "#/components/schemas/Address" "/withInvalidComposedModel": post: operationId: withInvalidComposedModel x-swagger-router-controller: TestController requestBody: content: "*/*": schema: "$ref": "#/components/schemas/ExtendedAddress" required: false responses: '200': description: success! "/withValidComposedModel": post: operationId: withValidComposedModel x-swagger-router-controller: TestController requestBody: content: "application/json": schema: "$ref": "#/components/schemas/ExtendedAddress" required: false responses: '200': description: success! "/withInvalidComposedModelArray": post: operationId: withInvalidComposedModelArray x-swagger-router-controller: TestController requestBody: content: "*/*": schema: type: array items: $ref: "#/components/schemas/ExtendedAddress" required: false responses: '200': description: success! "/unmappedWithModel/{id}": post: tags: - test2 operationId: unmappedWithModelInput x-swagger-router-controller: TestController parameters: - name: id in: path required: true schema: type: string requestBody: content: "application/json": schema: "$ref": "#/components/schemas/Address" required: false responses: '200': description: success! content: "application/json": schema: "$ref": "#/components/schemas/Address" "/mappedWithDefinedModel/{id}": post: tags: - test2 operationId: mappedWithDefinedModel x-swagger-router-controller: TestController parameters: - name: id in: path required: true schema: type: string requestBody: content: "application/json": schema: "$ref": "#/components/schemas/Dog" required: false responses: '200': description: success! content: "application/json": schema: "$ref": "#/components/schemas/Dog" "/unmappedWithUndefinedModel/{id}": post: tags: - test2 operationId: unmappedWithUndefinedModel x-swagger-router-controller: TestController parameters: - name: id in: path required: true schema: type: string requestBody: content: "application/json": schema: "$ref": "#/components/schemas/UnmappedModel" required: false responses: '200': description: success! "/withPath/{id}": get: tags: - test1 operationId: withPath x-swagger-router-controller: TestController parameters: - name: id in: path required: true schema: type: string responses: '200': description: success! content: "*/*": schema: "$ref": "#/components/schemas/User" "/withDate/{date}": get: tags: - test1 operationId: withDateTime x-swagger-router-controller: TestController parameters: - name: date in: path required: true schema: type: string format: date-time responses: '200': description: success! content: "application/json": schema: "$ref": "#/components/schemas/User" "/withIntegerEnum/{stage}": get: tags: - test1 operationId: withDateTime x-swagger-router-controller: TestController parameters: - name: stage in: path required: true schema: type: integer format: int64 enum: - 2147483647 - 3147483647 - 31474836475505055 - -9223372036854775808 responses: '200': description: success! content: "*/*": schema: "$ref": "#/components/schemas/User" "/overloaded": get: tags: - overloaded operationId: overloadedResponse x-swagger-router-controller: TestController parameters: - name: arg1 in: query schema: type: string responses: '200': description: success! content: "*/*": schema: "$ref": "#/components/schemas/User" "/throwApiException": get: tags: - throw operationId: throwApiException x-swagger-router-controller: TestController responses: '200': description: success! "/throwApiExceptionAsCause": get: tags: - throw operationId: throwApiExceptionAsCause x-swagger-router-controller: TestController responses: '200': description: success! "/throwNonApiException": get: tags: - throw operationId: throwNonApiException x-swagger-router-controller: TestController responses: '200': description: success! "/returnNonRfc2616Status": get: tags: - throw operationId: returnNonRfc2616Status x-swagger-router-controller: TestController responses: '200': description: success! "/responseHeaders": get: tags: - response operationId: returnWithResponseHeaders x-swagger-router-controller: TestController responses: '200': description: success externalDocs: description: Find out more about Swagger url: http://swagger.io components: schemas: Water: properties: clear: type: boolean name: type: string prices: type: array id: type: string format: uuid ExtendedAddress: type: object x-swagger-router-model: io.swagger.oas.test.models.ExtendedAddress allOf: - $ref: "#/components/schemas/Address" - type: object required: - gps properties: gps: type: string User: type: object properties: id: type: integer format: int64 name: type: string description: the name! example: | { "foo":"bar" } Address: required: - street type: object x-swagger-router-model: io.swagger.oas.test.models.Address properties: street: type: string example: 12345 El Monte Road city: type: string example: Los Altos Hills state: type: string example: CA zip: type: string example: '94022' UnmappedModel: properties: id: type: integer format: int64 name: type: string Animal: properties: id: type: integer format: int64 name: type: string address: "$ref": "#/components/schemas/Address" description: the name! Dog: type: object properties: id: type: integer format: int64 name: type: string dogType: type: string VeryComplexType: type: integer format: int32 ExtendedErrorModel: allOf: - type: object required: - rootCause properties: rootCause: type: string "$ref": "#/components/schemas/Category" Order: type: object not: type: integer format: int32 additionalProperties: type: integer properties: id: type: integer format: int64 petId: type: integer format: int64 quantity: type: integer format: int32 shipDate: type: string format: date-time status: type: string description: Order Status enum: - placed - approved - delivered complete: type: boolean default: false xml: name: Order Category: type: object properties: id: type: integer format: int64 name: type: string xml: name: Category Tag: type: object properties: id: type: integer format: int64 name: type: string xml: name: Tag Pet: type: object required: - name - photoUrls properties: id: type: integer format: int64 category: "$ref": "#/components/schemas/Category" user: type: string example: doggie photoUrls: type: array xml: name: photoUrl wrapped: true items: type: string tags: type: array xml: name: tag wrapped: true status: type: string description: pet status in the store enum: - available - pending - sold xml: name: Pet ApiResponse: type: object required: - name - photoUrls properties: code: type: integer format: int32 type: type: string message: type: string responses: NotFound: description: Entity not found. IllegalInput: description: Illegal input for operation. headers: X-Ref-Limit-Limit: "$ref": "#/components/headers/X-Rate-Limit-Reset" links: address: "$ref": "#/components/links/unsubscribe" GeneralError: description: General Error content: application/json: schema: $ref: "#/components/schemas/ExtendedErrorModel" parameters: contentParameter: in: query name: coordinates content: application/json: schema: $ref: "#/components/schemas/ExtendedErrorModel" examples: cat: summary: An example of a cat value: name: Fluffy petType: Cat color: White gender: male breed: Persian refParam: "$ref": "#/components/parameters/limitParam" newParam: name: skip in: query description: number of items to skip required: true schema: type: integer format: int32 "$ref": "#/components/schemas/Tag" skipParam: name: skip in: query description: number of items to skip required: true schema: type: integer format: int32 limitParam: name: limit in: query description: max records to return required: true schema: type: integer format: int32 examples: cat: summary: An example of a cat value: name: Fluffy petType: Cat color: White gender: male breed: Persian dog: summary: An example of a dog with a cat's name value: name: Puma petType: Dog color: Black gender: Female breed: Mixed frog: $ref: "#/components/examples/cat" requestBodies: requestBody1: description: request body in components content: application/json: description: Pet object that needs to be added to the store schema: "$ref": "#/components/schemas/Pet" application/xml: description: Pet object that needs to be added to the store schema: "$ref": "#/components/schemas/Pet" requestBody2: content: application/json: description: List of user object schema: type: array items: "$ref": "#/components/schemas/User" requestBody3: "$ref": "#/components/requestBodies/requestBody2" securitySchemes: reference: "$ref": "#/components/securitySchemes/api_key" petstore_auth: type: oauth2 flows: implicit: authorizationUrl: http://petstore.swagger.io/oauth/dialog scopes: write:pets: modify pets in your account read:pets: read your pets api_key: type: apiKey name: api_key in: header headers: X-Ref-Limit-Limit: "$ref": "#/components/headers/X-Rate-Limit-Reset" X-Rate-Limit-Limit: description: The number of allowed requests in the current period schema: type: integer example: "This is a header example" X-Rate-Limit-Remaining: description: The number of remaining requests in the current period schema: type: integer X-Rate-Limit-Reset: description: The number of seconds left in the current period content: application/json: schema: $ref: "#/components/schemas/ExtendedErrorModel" examples: dog: $ref: "#/components/examples/dog" links: referenced: "$ref": "#/components/links/unsubscribe" unsubscribe: operationId: cancelHookCallback parameters: id: $response.body#/hookId x-link: link extension callbacks: referenced: '$response.body#/failedUrl': "$ref": "#/components/callbacks/failed" heartbeat: '$request.query.heartbeat-url': post: requestBody: $ref: "#/components/requestBodies/requestBody3" responses: '200': description: Consumer acknowledged the callback failed: '$response.body#/failedUrl': post: requestBody: $ref: "#/components/requestBodies/requestBody3" responses: '200': description: Consumer acknowledged the callback failed success: '$response.body#/successUrl': post: requestBody: $ref: "#/components/requestBodies/requestBody1" responses: '200': description: Consumer acknowledged the callback x-component: - url: http://component.swagger.io/v2/swagger.json format: OAS version: '3.0' converter: url: https://github.com/mermade/oas3 version: 1.2.3 x-api-title: pet store test api in components ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/paramAndResponseRef.json ================================================ { "swagger": "2.0", "title": "Petstore Sample API", "info": { "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", "title": "Petstore Sample API", "contact": { "name": "Swagger API Team" }, "license": { "name": "MIT", "url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" } }, "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "user", "description": "Operations about user" }, { "name": "store", "description": "Access to Petstore orders", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } } ], "host": "petstore.swagger.io", "basePath": "/api", "paths": { "/pet": { "parameters": [ { "name": "body", "in": "body", "description": "Pet object that needs to be added to the store", "required": false, "schema": { "$ref": "#/definitions/Pet" } } ], "get": { "tags": [ "pet" ], "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet to fetch", "required": true, "type": "string" } ], "responses": { "200": { "description": "found it", "schema": { "$ref": "#/definitions/User" } }, "404": { "description": "Order not found" }, "400": { "description": "Invalid ID supplied" } } }, "put": { "tags": [ "pet" ], "parameters": [ { "name": "body", "in": "body", "description": "Pet object that needs to be added to the store", "required": false, "schema": { "$ref": "#/definitions/Pet" } } ], "responses": { "405": { "$ref": "http://my.company.com/responses/errors.json#/method-not-allowed" }, "404": { "$ref": "http://my.company.com/responses/errors.json#/not-found" }, "400": { "description": "Bad request" } } } } }, "definitions": { "User": { "properties": { "id": { "type": "integer", "format": "int32" }, "lastName": { "type": "string" }, "username": { "type": "string" }, "phone": { "type": "string" }, "email": { "type": "string" }, "userStatus": { "type": "integer", "format": "int32" }, "firstName": { "type": "string" }, "password": { "type": "string" } } }, "Category": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Pet": { "properties": { "id": { "type": "integer", "format": "int32" }, "tags": { "type": "array", "items": { "$ref": "#/definitions/Tag" } }, "category": { "$ref": "#/definitions/Category" }, "status": { "type": "string" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "items": { "type": "string" } } } }, "Tag": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Order": { "properties": { "id": { "type": "integer", "format": "int32" }, "orderTag": { "$ref": "#/definitions/OrderTag" }, "tag": { "$ref": "#/definitions/Tag" }, "petId": { "type": "integer", "format": "int32" }, "status": { "type": "string" }, "complete": { "type": "boolean" }, "quantity": { "type": "integer", "format": "int32" }, "shipDate": { "type": "string", "format": "date-time" } } }, "NoPropertiesModel": { }, "OrderTag": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/paramAndResponseRefArray.json ================================================ { "swagger": "2.0", "title": "Petstore Sample API", "info": { "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", "title": "Petstore Sample API", "contact": { "name": "Swagger API Team" }, "license": { "name": "MIT", "url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" } }, "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "user", "description": "Operations about user" }, { "name": "store", "description": "Access to Petstore orders", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } } ], "host": "petstore.swagger.io", "basePath": "/api", "paths": { "/pet": { "parameters": [ { "name": "body", "in": "body", "description": "Pet object that needs to be added to the store", "required": false, "schema": { "type": "array", "items": { "$ref": "#/definitions/Pet" } } } ], "get": { "tags": [ "pet" ], "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet to fetch", "required": true, "type": "string" } ], "responses": { "200": { "description": "found it", "schema": { "type": "array", "items": { "$ref": "#/definitions/User" } } }, "404": { "description": "Order not found" }, "400": { "description": "Invalid ID supplied" } } }, "put": { "tags": [ "pet" ], "parameters": [ { "name": "body", "in": "body", "description": "Pet object that needs to be added to the store", "required": false, "schema": { "type": "array", "items": { "$ref": "#/definitions/Pet" } } } ], "responses": { "405": { "$ref": "http://my.company.com/responses/errors.json#/method-not-allowed" }, "404": { "$ref": "http://my.company.com/responses/errors.json#/not-found" }, "400": { "description": "Bad request" } } } } }, "definitions": { "User": { "properties": { "id": { "type": "integer", "format": "int32" }, "lastName": { "type": "string" }, "username": { "type": "string" }, "phone": { "type": "string" }, "email": { "type": "string" }, "userStatus": { "type": "integer", "format": "int32" }, "firstName": { "type": "string" }, "password": { "type": "string" } } }, "Category": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Pet": { "properties": { "id": { "type": "integer", "format": "int32" }, "tags": { "type": "array", "items": { "$ref": "#/definitions/Tag" } }, "category": { "$ref": "#/definitions/Category" }, "status": { "type": "string" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "items": { "type": "string" } } } }, "Tag": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Order": { "properties": { "id": { "type": "integer", "format": "int32" }, "petId": { "type": "integer", "format": "int32" }, "status": { "type": "string" }, "complete": { "type": "boolean" }, "quantity": { "type": "integer", "format": "int32" }, "shipDate": { "type": "string", "format": "date-time" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/paramAndResponseRefComposed.json ================================================ { "swagger": "2.0", "title": "Petstore Sample API", "info": { "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", "title": "Petstore Sample API", "contact": { "name": "Swagger API Team" }, "license": { "name": "MIT", "url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" } }, "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "user", "description": "Operations about user" }, { "name": "store", "description": "Access to Petstore orders", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } } ], "host": "petstore.swagger.io", "basePath": "/api", "paths": { "/pet": { "get": { "tags": [ "pet" ], "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet to fetch", "required": true, "type": "string" } ], "responses": { "200": { "description": "found it" }, "404": { "description": "Order not found" }, "400": { "description": "Invalid ID supplied" } } }, "put": { "tags": [ "pet" ], "parameters": [ { "name": "body", "in": "body", "description": "Pet object that needs to be added to the store", "required": false, "schema": { "allOf": [ { "$ref": "#/definitions/User" }, { "$ref": "#/definitions/Pet" }, { "properties": { "id2": { "type": "integer", "format": "int32" } } } ] } } ], "responses": { "405": { "$ref": "http://my.company.com/responses/errors.json#/method-not-allowed" }, "404": { "$ref": "http://my.company.com/responses/errors.json#/not-found" }, "400": { "description": "Bad request" } } } } }, "definitions": { "User": { "properties": { "lastName": { "type": "string" }, "username": { "type": "string" }, "phone": { "type": "string" }, "email": { "type": "string" }, "userStatus": { "type": "integer", "format": "int32" }, "firstName": { "type": "string" }, "password": { "type": "string" } } }, "Category": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Pet": { "properties": { "id": { "type": "integer", "format": "int32" }, "tags": { "type": "array", "items": { "$ref": "#/definitions/Tag" } }, "category": { "$ref": "#/definitions/Category" }, "status": { "type": "string" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "items": { "type": "string" } } } }, "Tag": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Order": { "properties": { "id": { "type": "integer", "format": "int32" }, "petId": { "type": "integer", "format": "int32" }, "status": { "type": "string" }, "complete": { "type": "boolean" }, "quantity": { "type": "integer", "format": "int32" }, "shipDate": { "type": "string", "format": "date-time" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/pathRef.json ================================================ { "swagger": "2.0", "title": "Petstore Sample API", "info": { "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", "title": "Petstore Sample API", "contact": { "name": "Swagger API Team" }, "license": { "name": "MIT", "url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" } }, "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "user", "description": "Operations about user" }, { "name": "store", "description": "Access to Petstore orders", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } } ], "host": "petstore.swagger.io", "basePath": "/api", "paths": { "/pet": { "$ref": "http://my.company.com/paths/health.json" }, "/user": { "post": { "tags": [ "user" ], "parameters": [ { "name": "body", "in": "body", "description": "Created user object", "required": false, "schema": { "$ref": "#/definitions/User" } } ] } } }, "definitions": { "User": { "properties": { "id": { "type": "integer", "format": "int32" }, "lastName": { "type": "string" }, "username": { "type": "string" }, "phone": { "type": "string" }, "email": { "type": "string" }, "userStatus": { "type": "integer", "format": "int32" }, "firstName": { "type": "string" }, "password": { "type": "string" } } }, "Category": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Pet": { "properties": { "id": { "type": "integer", "format": "int32" }, "tags": { "type": "array", "items": { "$ref": "#/definitions/Tag" } }, "category": { "$ref": "#/definitions/Category" }, "status": { "type": "string" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "items": { "type": "string" } } } }, "Tag": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Order": { "properties": { "id": { "type": "integer", "format": "int32" }, "petId": { "type": "integer", "format": "int32" }, "status": { "type": "string" }, "complete": { "type": "boolean" }, "quantity": { "type": "integer", "format": "int32" }, "shipDate": { "type": "string", "format": "date-time" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/petstore-3.0-referred-schemas.json ================================================ { "openapi": "3.0.1", "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "user", "description": "Operations about user", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "store", "description": "Access to Petstore orders", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } } ], "paths": { "/pet": { "put": { "tags": [ "pet" ], "summary": "Update an existing pet", "operationId": "updatePet", "requestBody": { "description": "Pet object that needs to be added to the store", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RefName" } } }, "required": true }, "responses": { "400": { "description": "Invalid ID supplied" }, "404": { "description": "Pet not found" }, "405": { "description": "Validation exception" } } }, "post": { "tags": [ "pet" ], "summary": "Add a new pet to the store", "operationId": "addPet", "requestBody": { "description": "Pet object that needs to be added to the store", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } }, "application/xml": { "schema": { "$ref": "#/components/schemas/User" } } }, "required": true }, "responses": { "405": { "description": "Invalid input" } } } }, "/pet/findByTags": { "get": { "tags": [ "pet" ], "summary": "Finds Pets by tags", "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", "operationId": "findPetsByTags", "parameters": [ { "name": "tags", "in": "query", "description": "Tags to filter by", "required": true, "schema": { "type": "string" } } ], "responses": { "400": { "description": "Invalid tag value" }, "default": { "description": "Pets matching criteria", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Order" } } } } } } }, "/user": { "post": { "tags": [ "user" ], "summary": "User post", "description": "User post", "operationId": "postUser", "parameters": [ { "name": "body", "in": "body", "description": "Created user object", "required": false, "schema": { "$ref": "#/components/schemas/Order" } } ] } }, "/store": { "post": { "tags": [ "store" ], "summary": "Store post", "description": "Store post", "operationId": "postStore", "parameters": [ { "name": "body", "in": "body", "description": "order placed for purchasing the pet", "required": false, "schema": { "$ref": "#/components/schemas/Order" } } ] } } }, "components": { "schemas": { "Category": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "Category" } }, "PetHeader": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "PetHeader" } }, "Tag": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "Tag" } }, "Pet": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "category": { "$ref": "#/components/schemas/Category" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "xml": { "wrapped": true }, "items": { "type": "string", "xml": { "name": "photoUrl" } } }, "tags": { "type": "array", "xml": { "wrapped": true }, "items": { "$ref": "#/components/schemas/Tag", "xml": { "name": "tag" } } }, "status": { "type": "string", "description": "pet status in the store", "enum": [ "available,pending,sold" ] } }, "xml": { "name": "Pet" } }, "Order": { "properties": { "id": { "type": "integer", "format": "int32", "properties" : { "nested" : { "$ref" : "#/components/schemas/ReferredOrder" } } }, "petId": { "type": "integer", "format": "int32" }, "status": { "type": "string" }, "complete": { "type": "boolean" }, "quantity": { "type": "integer", "format": "int32" }, "shipDate": { "type": "string", "format": "date-time" } } }, "ReferredOrder": { "properties": { "id": { "type": "integer", "format": "int32", "properties" : { "nested" : { "$ref" : "#/components/schemas/RefName" } } } } }, "User": { "properties": { "lastName": { "type": "string" }, "username": { "type": "string" }, "phone": { "type": "string" }, "email": { "type": "string" }, "userStatus": { "type": "integer", "format": "int32" }, "firstName": { "type": "string" }, "password": { "type": "string" } } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/petstore-3.0-v2-ticket-3303.json ================================================ { "openapi": "3.0.1", "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "user", "description": "Operations about user" }, { "name": "store", "description": "Access to Petstore orders", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } } ], "paths": { "/pet/{petId}": { "get": { "summary": "Find pet by ID", "description": "Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions", "operationId": "getPetById", "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet that needs to be fetched", "required": true, "schema": { "type": "integer", "format": "int64" } }, { "name": "userId", "in": "path", "description": "ID of user to fetch", "required": true, "type": "string" }, { "name": "includeSecretDetails", "in": "query", "description": "secret: it's a secret", "required": false, "type": "boolean" } ], "responses": { "400": { "description": "Invalid ID supplied" }, "404": { "description": "Pet not found" }, "default": { "description": "The pet", "content": { "application/json": { "schema": { "type": "string" } }, "application/xml": { "schema": { "$ref": "#/components/schemas/Pet" } } }, "headers": { "X-Rate-Limit-Limit": { "description": "The number of allowed requests in the current period", "schema": { "$ref": "#/components/schemas/PetHeader" } }, "X-Rate-Limit-Remaining": { "description": "The number of remaining requests in the current period", "schema": { "type": "integer" } }, "X-Rate-Limit-Reset": { "description": "The number of seconds left in the current period", "schema": { "type": "integer" } } } } } } }, "/pet": { "put": { "tags": [ "pet" ], "summary": "Update an existing pet", "operationId": "updatePet", "requestBody": { "description": "Pet object that needs to be added to the store", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Category" } } }, "required": true }, "responses": { "400": { "description": "Invalid ID supplied" }, "404": { "description": "Pet not found" }, "405": { "description": "Validation exception" } } }, "post": { "summary": "Add a new pet to the store", "operationId": "addPet", "requestBody": { "description": "Pet object that needs to be added to the store", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } }, "required": true }, "responses": { "405": { "description": "Invalid input" } } } }, "/pet/findByStatus": { "get": { "summary": "Finds Pets by status", "description": "Multiple status values can be provided with comma separated strings", "operationId": "findPetsByStatus", "parameters": [ { "name": "status", "in": "query", "description": "Status values that need to be considered for filter", "required": true, "schema": { "type": "string" } }, { "name": "skip", "in": "query", "schema": { "type": "integer", "format": "int32" } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "format": "int32" } } ], "responses": { "400": { "description": "Invalid status value" }, "default": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } } } } } }, "/pet/findByTags": { "get": { "summary": "Finds Pets by tags", "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", "operationId": "findPetsByTags", "parameters": [ { "name": "tags", "in": "query", "description": "Tags to filter by", "required": true, "schema": { "type": "string" } } ], "responses": { "400": { "description": "Invalid tag value" }, "default": { "description": "Pets matching criteria", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } } } } } }, "/polymorphic": { "get": { "summary": "polymorphic Objects response", "responses": { "400": { "description": "Invalid status value" }, "default": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/polymorphicRoot" } } } } } } } }, "components": { "schemas": { "Category": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "Category" } }, "PetHeader": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "PetHeader" } }, "Tag": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "foo": { "$ref": "#/components/schemas/Foo" }, "name": { "type": "string" } }, "xml": { "name": "Tag" } }, "Foo": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "Foo" } }, "Bar": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "Bar" } }, "allOfparentA": { "type": "object", "properties": { "parentAStuff": { "type": "integer", "format": "int64" } } }, "allOfparentB": { "type": "object", "properties": { "parentAStuff": { "type": "integer", "format": "int64" } } }, "anyOfparentA": { "type": "object", "properties": { "parentCStuff": { "type": "integer", "format": "int64" } } }, "anyOfparentB": { "type": "object", "properties": { "parentCStuff": { "type": "integer", "format": "int64" } } }, "oneOfparentA": { "type": "object", "properties": { "parentBStuff": { "type": "integer", "format": "int64" } } }, "oneOfparentB": { "type": "object", "properties": { "parentBStuff": { "type": "integer", "format": "int64" } } }, "oneOfNestedParentA": { "type": "object", "properties": { "parentBStuff": { "type": "integer", "format": "int64" } } }, "oneOfNestedParentB": { "type": "object", "properties": { "parentBStuff": { "type": "integer", "format": "int64" } } }, "discriminatorMatchedChildA": { "type": "object", "properties": { "parentBStuff": { "type": "integer", "format": "int64" }, "discriminatorRefProperty": { "$ref": "#/components/schemas/discriminatorRefProperty" } } }, "discriminatorRefProperty": { "type": "object", "properties": { "parentBStuff": { "type": "integer", "format": "int64" } } }, "discriminatorMatchedChildB": { "type": "object", "properties": { "parentBStuff": { "type": "integer", "format": "int64" } } }, "discriminatorParentRefProperty": { "type": "object", "properties": { "parentBStuff": { "type": "integer", "format": "int64" } } }, "discriminatorParent": { "type": "object", "properties": { "parentBStuff": { "type": "integer", "format": "int64" }, "discriminatorParentRefProperty": { "$ref": "#/components/schemas/discriminatorParentRefProperty" } }, "discriminator": { "propertyName": "discriminatorKey", "mapping": { "A": "#/components/schemas/discriminatorMatchedChildA", "B": "#/components/schemas/discriminatorMatchedChildB" } } }, "allOfChild": { "allOf": [ { "$ref": "#/components/schemas/allOfparentA" }, { "$ref": "#/components/schemas/allOfparentB" } ] }, "anyOfChild": { "anyOf": [ { "$ref": "#/components/schemas/anyOfparentA" }, { "$ref": "#/components/schemas/anyOfparentB" } ] }, "oneOfChild": { "oneOf": [ { "$ref": "#/components/schemas/oneOfparentA" }, { "$ref": "#/components/schemas/oneOfparentB" }, { "$ref": "#/components/schemas/oneOfChildNested" } ] }, "oneOfChildNested": { "oneOf": [ { "$ref": "#/components/schemas/oneOfNestedParentB" }, { "$ref": "#/components/schemas/oneOfNestedParentA" } ] }, "polymorphicRoot": { "oneOf": [ { "$ref": "#/components/schemas/oneOfChild" }, { "$ref": "#/components/schemas/allOfChild" }, { "$ref": "#/components/schemas/anyOfChild" }, { "$ref": "#/components/schemas/discriminatorParent" } ] }, "Pet": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "category": { "$ref": "#/components/schemas/Category" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "xml": { "wrapped": true }, "items": { "type": "string", "xml": { "name": "photoUrl" } } }, "tags": { "type": "array", "xml": { "wrapped": true }, "items": { "$ref": "#/components/schemas/Tag", "xml": { "name": "tag" } } }, "status": { "type": "string", "description": "pet status in the store", "enum": [ "available,pending,sold" ] } }, "xml": { "name": "Pet" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/petstore-3.0-v2.json ================================================ { "openapi": "3.0.1", "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "user", "description": "Operations about user" }, { "name": "store", "description": "Access to Petstore orders", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } } ], "paths": { "/pet/{petId}": { "get": { "summary": "Find pet by ID", "description": "Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions", "operationId": "getPetById", "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet that needs to be fetched", "required": true, "schema": { "type": "integer", "format": "int64" } }, { "name": "userId", "in": "path", "description": "ID of user to fetch", "required": true, "type": "string" }, { "name": "includeSecretDetails", "in": "query", "description": "secret: it's a secret", "required": false, "type": "boolean" } ], "responses": { "400": { "description": "Invalid ID supplied" }, "404": { "description": "Pet not found" }, "default": { "description": "The pet", "content": { "application/json": { "schema": { "type": "string" } }, "application/xml": { "schema": { "$ref": "#/components/schemas/Pet" } } }, "headers": { "X-Rate-Limit-Limit": { "description": "The number of allowed requests in the current period", "schema": { "$ref": "#/components/schemas/PetHeader" } }, "X-Rate-Limit-Remaining": { "description": "The number of remaining requests in the current period", "schema": { "type": "integer" } }, "X-Rate-Limit-Reset": { "description": "The number of seconds left in the current period", "schema": { "type": "integer" } } } } } } }, "/pet": { "put": { "tags": [ "pet" ], "summary": "Update an existing pet", "operationId": "updatePet", "requestBody": { "description": "Pet object that needs to be added to the store", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Category" } } }, "required": true }, "responses": { "400": { "description": "Invalid ID supplied" }, "404": { "description": "Pet not found" }, "405": { "description": "Validation exception" } } }, "post": { "summary": "Add a new pet to the store", "operationId": "addPet", "requestBody": { "description": "Pet object that needs to be added to the store", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } }, "required": true }, "responses": { "405": { "description": "Invalid input" } } } }, "/pet/findByStatus": { "get": { "summary": "Finds Pets by status", "description": "Multiple status values can be provided with comma separated strings", "operationId": "findPetsByStatus", "parameters": [ { "name": "status", "in": "query", "description": "Status values that need to be considered for filter", "required": true, "schema": { "type": "string" } }, { "name": "skip", "in": "query", "schema": { "type": "integer", "format": "int32" } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "format": "int32" } } ], "responses": { "400": { "description": "Invalid status value" }, "default": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } } } } } }, "/pet/findByTags": { "get": { "summary": "Finds Pets by tags", "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", "operationId": "findPetsByTags", "parameters": [ { "name": "tags", "in": "query", "description": "Tags to filter by", "required": true, "schema": { "type": "string" } } ], "responses": { "400": { "description": "Invalid tag value" }, "default": { "description": "Pets matching criteria", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } } } } } } }, "components": { "schemas": { "Category": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "Category" } }, "PetHeader": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "PetHeader" } }, "Tag": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "foo": { "$ref": "#/components/schemas/Foo" }, "name": { "type": "string" } }, "xml": { "name": "Tag" } }, "Foo": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "Foo" } }, "Bar": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } }, "xml": { "name": "Bar" } }, "Pet": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, "category": { "$ref": "#/components/schemas/Category" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "xml": { "wrapped": true }, "items": { "type": "string", "xml": { "name": "photoUrl" } } }, "tags": { "type": "array", "xml": { "wrapped": true }, "items": { "$ref": "#/components/schemas/Tag", "xml": { "name": "tag" } } }, "status": { "type": "string", "description": "pet status in the store", "enum": [ "available,pending,sold" ] } }, "xml": { "name": "Pet" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/petstore-3.0-v2_withoutModels.json ================================================ { "openapi": "3.0.1", "paths": { "/pet/{petId}": { "get": { "summary": "Find pet by ID", "description": "Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions", "operationId": "getPetById", "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet that needs to be fetched", "required": true } ], "responses": { "400": { "description": "Invalid ID supplied" }, "404": { "description": "Pet not found" } } } }, "/pet": { "put": { "summary": "Update an existing pet", "operationId": "updatePet", "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet that needs to be fetched", "required": true } ], "responses": { "400": { "description": "Invalid ID supplied" }, "404": { "description": "Pet not found" }, "405": { "description": "Validation exception" } } }, "post": { "summary": "Add a new pet to the store", "operationId": "addPet", "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet that needs to be fetched", "required": true } ], "responses": { "405": { "description": "Invalid input" } } } }, "/pet/findByStatus": { "get": { "summary": "Finds Pets by status", "description": "Multiple status values can be provided with comma separated strings", "operationId": "findPetsByStatus", "parameters": [ { "name": "status", "in": "query", "description": "Status values that need to be considered for filter", "required": true }, { "name": "skip", "in": "query" }, { "name": "limit", "in": "query" } ], "responses": { "400": { "description": "Invalid status value" } } } }, "/pet/findByTags": { "get": { "summary": "Finds Pets by tags", "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", "operationId": "findPetsByTags", "parameters": [ { "name": "tags", "in": "query", "description": "Tags to filter by", "required": true } ], "responses": { "400": { "description": "Invalid tag value" } } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/petstore-3.0.json ================================================ { "info": { "version": "1.0.0", "license": { "name": "MIT" }, "title": "Swagger Petstore" }, "paths": { "/pets": { "post": { "tags": [ "pets" ], "summary": "Create a pet", "responses": { "default": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }, "description": "unexpected error" }, "201": { "description": "Null response" } }, "operationId": "createPets" }, "get": { "tags": [ "pets" ], "summary": "List all pets", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pets" } } }, "headers": { "x-next": { "description": "A link to the next page of responses", "schema": { "type": "string" } } }, "description": "An paged array of pets" }, "default": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }, "description": "unexpected error" } }, "parameters": [ { "required": false, "in": "query", "description": "How many items to return at one time (max 100)", "name": "limit", "schema": { "type": "integer", "format": "int32" } } ], "operationId": "listPets" } }, "/pets/{petId}": { "get": { "tags": [ "pets" ], "summary": "Info for a specific pet", "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pets" } } }, "description": "Expected response to a valid request" }, "default": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }, "description": "unexpected error" } }, "parameters": [ { "required": true, "in": "path", "description": "The id of the pet to retrieve", "name": "petId", "schema": { "type": "string" } } ], "operationId": "showPetById" } } }, "openapi": "3.0.1", "components": { "schemas": { "Pet": { "required": [ "id", "name" ], "properties": { "tag": { "type": "string" }, "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" } } }, "Pets": { "items": { "$ref": "#/components/schemas/Pet" }, "type": "array" }, "Error": { "required": [ "code", "message" ], "properties": { "message": { "type": "string" }, "code": { "type": "integer", "format": "int32" } } } } }, "servers": [ { "url": "http://petstore.swagger.io/v1" } ] } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/petstore-3.0.yaml ================================================ openapi: "3.0.1" info: version: 1.0.0 title: Swagger Petstore license: name: MIT servers: - url: http://petstore.swagger.io/v1 paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: "200": description: An paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" post: summary: Create a pet operationId: createPets tags: - pets responses: "201": description: Null response default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById tags: - pets parameters: - name: petId in: path required: true description: The id of the pet to retrieve schema: type: string responses: "200": description: Expected response to a valid request content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" components: schemas: Pet: required: - id - name properties: id: type: integer format: int64 name: type: string tag: type: string Pets: type: array items: $ref: "#/components/schemas/Pet" Error: required: - code - message properties: code: type: integer format: int32 message: type: string ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/petstore.json ================================================ { "swagger": "2.0", "title": "Petstore Sample API", "info": { "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", "title": "Petstore Sample API", "contact": { "name": "Swagger API Team" }, "license": { "name": "MIT", "url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" }, "x-name" : "value", "x-extension" : { "name" : "value" } }, "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "user", "description": "Operations about user" }, { "name": "store", "description": "Access to Petstore orders", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } } ], "host": "petstore.swagger.io", "basePath": "/api", "paths": { "/pet": { "put": { "tags": [ "pet" ], "parameters": [ { "name": "body", "in": "body", "description": "Pet object that needs to be added to the store", "required": false, "schema": { "$ref": "#/definitions/Pet" } } ], "responses": { "405": { "description": "Validation exception" }, "404": { "description": "Pet not found" }, "400": { "description": "Invalid ID supplied" } }, "x-name" : "value", "x-extension" : { "name" : "value" } }, "post": { "tags": [ "pet" ], "parameters": [ { "name": "body", "in": "body", "description": "Pet object that needs to be added to the store", "required": false, "schema": { "$ref": "#/definitions/Tag" } } ], "responses": { "405": { "description": "Invalid input" } } } }, "/user/createWithList": { "post": { "tags": [ "user" ], "parameters": [ { "name": "body", "in": "body", "description": "List of user object", "required": false } ] } }, "/store/order/{orderId}": { "get": { "tags": [ "store" ], "parameters": [ { "name": "orderId", "in": "path", "description": "ID of pet that needs to be fetched", "required": true, "type": "string" } ], "responses": { "404": { "description": "Order not found" }, "400": { "description": "Invalid ID supplied" } } }, "delete": { "tags": [ "store" ], "parameters": [ { "name": "orderId", "in": "path", "description": "ID of the order that needs to be deleted", "required": true, "type": "string" } ], "responses": { "404": { "description": "Order not found" }, "400": { "description": "Invalid ID supplied" } } } }, "/user/createWithArray": { "post": { "tags": [ "user" ], "parameters": [ { "name": "body", "in": "body", "description": "List of user object", "required": false, "schema": { "$ref": "#/definitions/User" } } ] } }, "/store/order": { "post": { "tags": [ "store" ], "parameters": [ { "name": "body", "in": "body", "description": "order placed for purchasing the pet", "required": false, "schema": { "$ref": "#/definitions/Order" } } ], "responses": { "400": { "description": "Invalid Order" } } } }, "/pet/findByStatus": { "get": { "tags": [ "pet" ], "parameters": [ { "name": "status", "in": "query", "description": "Status values that need to be considered for filter", "required": false, "type": "string" } ], "responses": { "400": { "description": "Invalid status value" } } } }, "/user/{username}": { "get": { "tags": [ "user" ], "parameters": [ { "name": "username", "in": "path", "description": "The name that needs to be fetched. Use user1 for testing. ", "required": true, "type": "string" } ], "responses": { "404": { "description": "User not found" }, "400": { "description": "Invalid username supplied" } } }, "put": { "tags": [ "user" ], "parameters": [ { "name": "username", "in": "path", "description": "name that need to be deleted", "required": true, "type": "string" }, { "name": "body", "in": "body", "description": "Updated user object", "required": false, "schema": { "$ref": "#/definitions/User" } } ], "responses": { "404": { "description": "User not found" }, "400": { "description": "Invalid user supplied" } } }, "delete": { "tags": [ "user" ], "parameters": [ { "name": "username", "in": "path", "description": "The name that needs to be deleted", "required": true, "type": "string" } ], "responses": { "404": { "description": "User not found" }, "400": { "description": "Invalid username supplied" } } } }, "/pet/findByTags": { "get": { "tags": [ "pet" ], "parameters": [ { "name": "tags", "in": "query", "description": "Tags to filter by", "required": false, "type": "string" } ], "responses": { "400": { "description": "Invalid tag value" } } } }, "/user": { "post": { "tags": [ "user" ], "parameters": [ { "name": "body", "in": "body", "description": "Created user object", "required": false, "schema": { "$ref": "#/definitions/User" } } ] } }, "/pet/{petId}": { "get": { "tags": [ "pet" ], "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet that needs to be fetched", "required": true, "type": "string" } ], "responses": { "404": { "description": "Pet not found" }, "400": { "description": "Invalid ID supplied" } } }, "head": { "tags": [ "pet" ], "parameters": [ { "name": "petId", "in": "path", "description": "ID of pet that needs to be fetched", "required": true, "type": "string" } ], "responses": { "404": { "description": "Pet not found" }, "400": { "description": "Invalid ID supplied" } } } }, "/user/logout": { "get": { "tags": [ "user" ] } }, "/user/login": { "get": { "tags": [ "user" ], "parameters": [ { "name": "username", "in": "query", "description": "The user name for login", "required": false, "type": "string" }, { "name": "password", "in": "query", "description": "The password for login in clear text", "required": false, "type": "string" } ], "responses": { "400": { "description": "Invalid username/password supplied" } } } } }, "definitions": { "User": { "properties": { "id": { "type": "integer", "format": "int32" }, "lastName": { "type": "string" }, "username": { "type": "string" }, "phone": { "type": "string" }, "email": { "type": "string" }, "userStatus": { "type": "integer", "format": "int32" }, "firstName": { "type": "string" }, "password": { "type": "string" } } }, "Category": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Pet": { "properties": { "id": { "type": "integer", "format": "int32" }, "tags": { "type": "array", "items": { "$ref": "#/definitions/Tag" } }, "category": { "$ref": "#/definitions/Category" }, "status": { "type": "string" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "items": { "type": "string" } } } }, "Tag": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Order": { "properties": { "id": { "type": "integer", "format": "int32" }, "petId": { "type": "integer", "format": "int32" }, "status": { "type": "string" }, "complete": { "type": "boolean" }, "quantity": { "type": "integer", "format": "int32" }, "shipDate": { "type": "string", "format": "date-time" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/propertiesWithConstraints.json ================================================ { "oas": "3.0.1", "paths": { "/health": { "get": { "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/Health" } } } } } }, "components": { "schemas": { "Health": { "properties": { "array_with_min": { "type": "array", "minItems": 5, "items": { "$ref": "#/definitions/Health" } }, "array_with_max": { "type": "array", "maxItems": 10, "items": { "$ref": "#/definitions/Health" } }, "array_with_unique": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/definitions/Health" } }, "array_with_all": { "type": "array", "minItems": 1, "maxItems": 10, "uniqueItems": true, "items": { "$ref": "#/definitions/Health" } }, "string_with_constraints": { "type": "string", "minLength": 10, "maxLength": 100, "pattern": "apattern" } } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/propertyWithVendorExtensions.json ================================================ { "swagger": "2.0", "x-string-value": "Hello World", "x-null-value": null, "x-map-value": { "hello": "world", "foo": "bar" }, "x-list-value": [ "Hello", "World" ], "x-number-value": 123, "x-boolean-value": true, "not-an-extension": "foobar", "paths": { "/health": { "get": { "responses": { "200": { "description": "Success", "schema": { "$ref": "#/definitions/Health" } } } } } }, "components": { "schemas": { "Health": { "properties": { "status": { "type": "string", "x-string-value": "Hello World", "x-null-value": null, "x-map-value": { "hello": "world", "foo": "bar" }, "x-list-value": [ "Hello", "World" ], "x-number-value": 123, "x-boolean-value": true, "not-an-extension": "foobar" }, "array": { "type": "array", "items": { "$ref": "#/definitions/Health" }, "x-string-value": "string_value" } } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/recursivemodels.json ================================================ { "openapi": "3.0.1", "tags": [ { "name": "Recursive Model Resource" } ], "paths": { "/r/indirect": { "get": { "tags": [ "Recursive Model Resource" ], "operationId": "getIndirectRecursiveModel", "responses": { "200": { "description": "successful operation", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IndirectRecursiveModelA" } }, "application/xml": { "schema": { "$ref": "#/components/schemas/IndirectRecursiveModelA" } } } } } } }, "/r/self": { "get": { "tags": [ "Recursive Model Resource" ], "operationId": "getSelfReferencingModel", "parameters": [], "responses": { "200": { "description": "successful operation", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SelfReferencingModel" } }, "application/xml": { "schema": { "$ref": "#/components/schemas/SelfReferencingModel" } } } } } } } }, "components": { "schemas": { "SelfReferencingModel": { "type": "object", "properties": { "id": { "type": "integer", "format": "int32" }, "children": { "type": "array", "properties": { "nested": { "$ref": "#/components/schemas/SelfReferencingModel" } } } } }, "IndirectRecursiveModelA": { "type": "object", "properties": { "id": { "type": "integer", "format": "int32" }, "indirectRecursiveModelB": { "$ref": "#/components/schemas/IndirectRecursiveModelB" } } }, "IndirectRecursiveModelB": { "type": "object", "properties": { "id": { "type": "integer", "format": "int32" }, "indirectRecursiveModelA": { "$ref": "#/components/schemas/IndirectRecursiveModelA" } } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/responseRef.json ================================================ { "swagger": "2.0", "title": "Petstore Sample API", "info": { "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", "title": "Petstore Sample API", "contact": { "name": "Swagger API Team" }, "license": { "name": "MIT", "url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" } }, "tags": [ { "name": "pet", "description": "Everything about your Pets", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } }, { "name": "user", "description": "Operations about user" }, { "name": "store", "description": "Access to Petstore orders", "externalDocs": { "description": "Find out more", "url": "http://swagger.io" } } ], "host": "petstore.swagger.io", "basePath": "/api", "paths": { "/pet": { "put": { "tags": [ "pet" ], "parameters": [ { "name": "body", "in": "body", "description": "Pet object that needs to be added to the store", "required": false, "schema": { "$ref": "#/definitions/Pet" } } ], "responses": { "405": { "$ref": "http://my.company.com/responses/errors.json#/method-not-allowed" }, "404": { "$ref": "http://my.company.com/responses/errors.json#/not-found" }, "400": { "description": "Bad request" } } } } }, "definitions": { "User": { "properties": { "id": { "type": "integer", "format": "int32" }, "lastName": { "type": "string" }, "username": { "type": "string" }, "phone": { "type": "string" }, "email": { "type": "string" }, "userStatus": { "type": "integer", "format": "int32" }, "firstName": { "type": "string" }, "password": { "type": "string" } } }, "Category": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Pet": { "properties": { "id": { "type": "integer", "format": "int32" }, "tags": { "type": "array", "items": { "$ref": "#/definitions/Tag" } }, "category": { "$ref": "#/definitions/Category" }, "status": { "type": "string" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "items": { "type": "string" } } } }, "Tag": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Order": { "properties": { "id": { "type": "integer", "format": "int32" }, "petId": { "type": "integer", "format": "int32" }, "status": { "type": "string" }, "complete": { "type": "boolean" }, "quantity": { "type": "integer", "format": "int32" }, "shipDate": { "type": "string", "format": "date-time" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/sampleSpec.json ================================================ { "swagger": "2.0", "title": "XXX", "info": { "description": "YYY", "title": "ZZZ", "contact": { "name": "AAA" }, "license": { "name": "MIT", "url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" } }, "basePath": "/api", "paths": { "/users": { "get": { "tags": [ "users" ], "parameters": [ { "name": "userId", "in": "path", "description": "ID of user to fetch", "required": true, "type": "string" }, { "name": "includeSecretDetails", "in": "query", "description": "secret: it's a secret", "required": false, "type": "boolean" } ], "responses": { "200": { "description": "found it", "schema": { "$ref": "Order" } }, "404": { "description": "Order not found" }, "400": { "description": "Invalid ID supplied" } } } } }, "definitions": { "User": { "properties": { "id": { "type": "integer", "format": "int32" }, "lastName": { "type": "string" }, "username": { "type": "string" }, "phone": { "type": "string" }, "email": { "type": "string" }, "userStatus": { "type": "integer", "format": "int32" }, "firstName": { "type": "string" }, "password": { "type": "string" } } }, "Category": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Pet": { "properties": { "id": { "type": "integer", "format": "int32" }, "tags": { "type": "array", "items": { "$ref": "#/definitions/Tag" } }, "category": { "$ref": "#/definitions/Category" }, "status": { "type": "string" }, "name": { "type": "string" }, "photoUrls": { "type": "array", "items": { "type": "string" } } } }, "Tag": { "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string" } } }, "Order": { "properties": { "_id": { "type": "string" }, "id": { "type": "integer", "format": "int32" }, "petId": { "type": "integer", "format": "int32" }, "status": { "type": "string" }, "complete": { "type": "boolean" }, "quantity": { "type": "integer", "format": "int32" }, "shipDate": { "type": "string", "format": "date-time" } } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/securityDefinitions.json ================================================ { "openapi": "3.0.1", "info": { "version": "1.0.0", "license": { "name": "MIT" }, "title": "Swagger Petstore" }, "servers": [ { "url": "http://petstore.swagger.io/v1" } ], "paths": {}, "security": [ { "petstore_auth": [ "write:pets", "read:pets" ] }, { "api_key": [] }, { "http": [] } ], "components": { "securitySchemes": { "petstore_auth": { "type": "oauth2", "flows": { "implicit": { "authorizationUrl": "http://petstore.swagger.io/oauth/dialog", "scopes": { "write:pets": "modify pets in your account", "read:pets": "read your pets" } } } }, "api_key": { "type": "apiKey", "name": "api_key", "in": "header" }, "http": { "type": "http", "scheme": "basic" }, "open_id_connect": { "type": "openIdConnect", "openIdConnectUrl": "http://petstore.swagger.io/openid" } } } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/securitySchemaWithExtension.json ================================================ { "type": "oauth2", "flows": { "implicit": { "authorizationUrl": "http://petstore.swagger.io/oauth/dialog", "scopes": { "write:pets": "modify pets in your account", "read:pets": "read your pets" } } }, "x-custom": { "key-string": "value-one" } } ================================================ FILE: modules/swagger-core/src/test/resources/specFiles/swos-126.yaml ================================================ openapi: 3.0.0 info: title: ExampleBuilder and date-time examples version: 0.0.0 paths: {} components: schemas: MyModel: type: object properties: date: type: string format: date example: '2019-08-05' dateTime: type: string format: date-time example: '2019-08-05T12:34:56Z' ================================================ FILE: modules/swagger-core/src/test/resources/testOAS31/basicOAS31.yaml ================================================ openapi: "3.1.0" info: version: 1.0.0 title: Swagger Petstore license: name: MIT identifier: test servers: - url: http://petstore.swagger.io/v1 webhooks: # Each webhook needs a name newPet: # This is a Path Item Object, the only difference is that the request is initiated by the API provider post: requestBody: description: Information about a new pet in the system content: application/json: schema: $ref: "#/components/schemas/Pet" description: pet responses: "200": description: Return a 200 status to indicate that the data was received successfully paths: /pets: get: summary: List all pets operationId: listPets tags: - pets parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: "200": description: An paged array of pets headers: x-next: description: A link to the next page of responses schema: type: string content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" description: error post: summary: Create a pet operationId: createPets tags: - pets responses: "201": description: Null response default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Tag" /pets/{petId}: get: summary: Info for a specific pet operationId: showPetById tags: - pets parameters: - name: petId in: path required: true description: The id of the pet to retrieve schema: type: string - $ref: "#/components/parameters/User" description: user summary: user responses: "200": description: Expected response to a valid request content: application/json: schema: $ref: "#/components/schemas/Pets" default: description: unexpected error content: application/json: schema: $ref: "#/components/schemas/Error" components: parameters: User: in: query description: user name: user schema: type: string schemas: Pet: type: - object - string required: - id - name properties: id: type: integer format: int64 name: type: string testenum: type: string enum: - available - pending - sold default: available testconst: type: string const: pending tag: type: string arbitraryKeyword: test Pets: type: array items: $ref: "#/components/schemas/Pet" Error: required: - code - message properties: code: type: integer format: int32 message: type: string tag: $ref: "#/components/schemas/Tag" Tag: type: - object - string - string - foo properties: id: type: integer format: int64 name: type: string ================================================ FILE: modules/swagger-core/src/test/resources/uber.json ================================================ { "swagger": "2", "info": { "title": "Uber API", "description": "Move your app forward with the Uber API", "version": "1.0.0" }, "host": "api.uber.com", "schemes": [ "https" ], "basePath": "/v1", "produces": [ "application/json" ], "paths": { "/products": { "get": { "summary": "Product Types", "description": "The Products endpoint returns information about the Uber products offered at a given location. The response includes the display name and other details about each product, and lists the products in the proper display order.", "parameters": [ { "name": "latitude", "in": "query", "description": "Latitude component of location.", "required": true, "type": "number", "format": "double" }, { "name": "longitude", "in": "query", "description": "Longitude component of location.", "required": true, "type": "number", "format": "double" } ], "tags": [ "Products" ], "responses": { "200": { "description": "An array of products", "schema": { "type": "array", "items": { "$ref": "Product" } } }, "default": { "description": "Unexpected error", "schema": { "$ref": "Error" } } } } }, "/estimates/price": { "get": { "summary": "Price Estimates", "description": "The Price Estimates endpoint returns an estimated price range for each product offered at a given location. The price estimate is provided as a formatted string with the full price range and the localized currency symbol.

The response also includes low and high estimates, and the [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code for situations requiring currency conversion. When surge is active for a particular product, its surge_multiplier will be greater than 1, but the price estimate already factors in this multiplier.", "parameters": [ { "name": "start_latitude", "in": "query", "description": "Latitude component of start location.", "required": true, "type": "number", "format": "double" }, { "name": "start_longitude", "in": "query", "description": "Longitude component of start location.", "required": true, "type": "number", "format": "double" }, { "name": "end_latitude", "in": "query", "description": "Latitude component of end location.", "required": true, "type": "number", "format": "double" }, { "name": "end_longitude", "in": "query", "description": "Longitude component of end location.", "required": true, "type": "number", "format": "double" } ], "tags": [ "Estimates" ], "responses": { "200": { "description": "An array of price estimates by product", "schema": { "type": "array", "items": { "$ref": "PriceEstimate" } } }, "default": { "description": "Unexpected error", "schema": { "$ref": "Error" } } } } }, "/estimates/time": { "get": { "summary": "Time Estimates", "description": "The Time Estimates endpoint returns ETAs for all products offered at a given location, with the responses expressed as integers in seconds. We recommend that this endpoint be called every minute to provide the most accurate, up-to-date ETAs.", "parameters": [ { "name": "start_latitude", "in": "query", "description": "Latitude component of start location.", "required": true, "type": "number", "format": "double" }, { "name": "start_longitude", "in": "query", "description": "Longitude component of start location.", "required": true, "type": "number", "format": "double" }, { "name": "customer_uuid", "in": "query", "type": "string", "format": "uuid", "description": "Unique customer identifier to be used for experience customization." }, { "name": "product_id", "in": "query", "type": "string", "description": "Unique identifier representing a specific product for a given latitude & longitude." } ], "tags": [ "Estimates" ], "responses": { "200": { "description": "An array of products", "schema": { "type": "array", "items": { "$ref": "Product" } } }, "default": { "description": "Unexpected error", "schema": { "$ref": "Error" } } } } }, "/me": { "get": { "summary": "User Profile", "description": "The User Profile endpoint returns information about the Uber user that has authorized with the application.", "tags": [ "User" ], "responses": { "200": { "description": "Profile information for a user", "schema": { "$ref": "Profile" } }, "default": { "description": "Unexpected error", "schema": { "$ref": "Error" } } } } }, "/history": { "get": { "summary": "User Activity", "description": "The User Activity endpoint returns data about a user's lifetime activity with Uber. The response will include pickup locations and times, dropoff locations and times, the distance of past requests, and information about which products were requested.

The history array in the response will have a maximum length based on the limit parameter. The response value count may exceed limit, therefore subsequent API requests may be necessary.", "parameters": [ { "name": "offset", "in": "query", "type": "integer", "format": "int32", "description": "Offset the list of returned results by this amount. Default is zero." }, { "name": "limit", "in": "query", "type": "integer", "format": "int32", "description": "Number of items to retrieve. Default is 5, maximum is 100." } ], "tags": [ "User" ], "responses": { "200": { "description": "History information for the given user", "schema": { "$ref": "Activities" } }, "default": { "description": "Unexpected error", "schema": { "$ref": "Error" } } } } } }, "definitions": { "Product": { "properties": { "product_id": { "type": "string", "description": "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles." }, "description": { "type": "string", "description": "Description of product." }, "display_name": { "type": "string", "description": "Display name of product." }, "capacity": { "type": "string", "description": "Capacity of product. For example, 4 people." }, "image": { "type": "string", "description": "Image URL representing the product." } } }, "PriceEstimate": { "properties": { "product_id": { "type": "string", "description": "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles" }, "currency_code": { "type": "string", "description": "[ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code." }, "display_name": { "type": "string", "description": "Display name of product." }, "estimate": { "type": "string", "description": "Formatted string of estimate in local currency of the start location. Estimate could be a range, a single number (flat rate) or \"Metered\" for TAXI." }, "low_estimate": { "type": "number", "description": "Lower bound of the estimated price." }, "high_estimate": { "type": "number", "description": "Upper bound of the estimated price." }, "surge_multiplier": { "type": "number", "description": "Expected surge multiplier. Surge is active if surge_multiplier is greater than 1. Price estimate already factors in the surge multiplier." } } }, "Profile": { "properties": { "first_name": { "type": "string", "description": "First name of the Uber user." }, "last_name": { "type": "string", "description": "Last name of the Uber user." }, "email": { "type": "string", "description": "Email address of the Uber user" }, "picture": { "type": "string", "description": "Image URL of the Uber user." }, "promo_code": { "type": "string", "description": "Promo code of the Uber user." } } }, "Activity": { "properties": { "uuid": { "type": "string", "description": "Unique identifier for the activity" } } }, "Activities": { "properties": { "offset": { "type": "integer", "format": "int32", "description": "Position in pagination." }, "limit": { "type": "integer", "format": "int32", "description": "Number of items to retrieve (100 max)." }, "count": { "type": "integer", "format": "int32", "description": "Total number of items available." }, "history": { "type": "array", "$ref": "Activity" } } }, "Error": { "properties": { "code": { "type": "integer", "format": "int32" }, "message": { "type": "string" }, "fields": { "type": "string" } } } } } ================================================ FILE: modules/swagger-eclipse-transformer-maven-plugin/README.md ================================================ Adapted from https://github.com/eclipse/transformer/blob/main/org.eclipse.transformer.maven not to add the transformed JAR as an attached artifact to the project. To be replaced with Eclipse original Transformer plugin when/if optional attachment is supported. ================================================ FILE: modules/swagger-eclipse-transformer-maven-plugin/pom.xml ================================================ io.swagger.core.v3 swagger-project 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-eclipse-transformer-maven-plugin swagger-eclipse-transformer-maven-plugin swagger-eclipse-transformer-maven-plugin maven-plugin 3.9.9 0.20 3.3.0 1.2.6 3.18.1 org.apache.maven.plugins maven-enforcer-plugin ${enforcer-plugin-version} true org.apache.maven.plugins maven-jar-plugin 3.3.0 org.apache.maven.plugins maven-plugin-plugin 3.6.4 transform org.eclipse.transformer org.eclipse.transformer.cli 0.2.0 javax.inject javax.inject 1 compile org.apache.maven maven-plugin-api ${maven.target.version} provided org.codehaus.plexus plexus-utils org.codehaus.plexus plexus-component-annotations org.codehaus.plexus plexus-classworlds org.apache.maven maven-core ${maven.target.version} provided org.codehaus.plexus plexus-utils org.apache.maven.plugin-tools maven-plugin-annotations 3.15.1 provided org.apache.maven maven-artifact org.codehaus.plexus plexus-archiver 4.10.0 test org.codehaus.plexus plexus-utils org.apache.commons commons-compress org.codehaus.plexus plexus-utils 4.0.2 org.codehaus.plexus plexus-component-annotations 2.2.0 org.apache.maven maven-model ${maven.target.version} provided commons-cli commons-cli 1.9.0 org.apache.maven maven-artifact ${maven.target.version} provided org.apache.maven maven-compat ${maven.target.version} provided org.codehaus.plexus plexus-utils ================================================ FILE: modules/swagger-eclipse-transformer-maven-plugin/src/main/java/io/swagger/v3/oas/transformer/TransformMojo.java ================================================ package io.swagger.v3.oas.transformer; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; import org.eclipse.transformer.Transformer; import org.eclipse.transformer.jakarta.JakartaTransformer; /** * * Adapted from https://github.com/eclipse/transformer/blob/main/org.eclipse.transformer.maven * not to add the transformed JAR as an attached artifact to the project. * * To be replaced with Eclipse original Transformer plugin when/if optional attachment is supported. * * This is a Maven plugin which runs the Eclipse Transformer on build artifacts * as part of the build. */ @Mojo(name = "run", requiresDependencyResolution = ResolutionScope.RUNTIME_PLUS_SYSTEM, defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, threadSafe = true) public class TransformMojo extends AbstractMojo { @Parameter(defaultValue = "${project}", readonly = true, required = true) private MavenProject project; @Parameter(defaultValue = "false", property = "transformer-plugin.invert", required = true) private Boolean invert; @Parameter(defaultValue = "true", property = "transformer-plugin.overwrite", required = true) private Boolean overwrite; @Parameter(property = "transformer-plugin.renames", defaultValue = "") private String rulesRenamesUri; @Parameter(property = "transformer-plugin.versions", defaultValue = "") private String rulesVersionUri; @Parameter(property = "transformer-plugin.bundles", defaultValue = "") private String rulesBundlesUri; @Parameter(property = "transformer-plugin.direct", defaultValue = "") private String rulesDirectUri; @Parameter(property = "transformer-plugin.per-class-constant", defaultValue = "") private String rulesPerClassConstantUri; @Parameter(property = "transformer-plugin.xml", defaultValue = "") private String rulesXmlsUri; @Parameter(defaultValue = "transformed") private String classifier; private static final int MAX_LOG_BUFFER_SIZE = 16 * 1024; @Parameter(defaultValue = "${project.build.directory}", required = true) private File outputDirectory; @Parameter(defaultValue = "true", property = "transformer-plugin.attach", required = true) private Boolean attach; @Component private MavenProjectHelper projectHelper; /** * Main execution point of the plugin. This looks at the attached artifacts, * and runs the transformer on them. * * @throws MojoFailureException Thrown if there is an error during plugin * execution */ @Override public void execute() throws MojoFailureException { final Transformer transformer = getTransformer(); final Artifact[] sourceArtifacts = getSourceArtifacts(); for (final Artifact sourceArtifact : sourceArtifacts) { transform(transformer, sourceArtifact); } } /** * This runs the transformation process on the source artifact with the * transformer provided. The transformed artifact is attached to the * project. * * @param transformer The Transformer to use for the transformation * @param sourceArtifact The Artifact to transform * @throws MojoFailureException if plugin execution fails */ public void transform(final Transformer transformer, final Artifact sourceArtifact) throws MojoFailureException { final String sourceClassifier = sourceArtifact.getClassifier(); final String targetClassifier = (sourceClassifier == null || sourceClassifier.length() == 0) ? this.classifier : sourceClassifier + "-" + this.classifier; final File targetFile = new File(outputDirectory, sourceArtifact.getArtifactId() + "-" + targetClassifier + "-" + sourceArtifact.getVersion() + "." + sourceArtifact.getType()); final List args = new ArrayList<>(); args.add(sourceArtifact.getFile() .getAbsolutePath()); args.add(targetFile.getAbsolutePath()); if (this.overwrite) { args.add("-o"); } transformer.setArgs(args.toArray(new String[0])); int rc = transformer.run(); if (rc != 0) { throw new MojoFailureException("Transformer failed with an error: " + Transformer.RC_DESCRIPTIONS[rc]); } if (attach) { projectHelper.attachArtifact(project, sourceArtifact.getType(), targetClassifier, targetFile); } } /** * Builds a configured transformer for the specified source and target * artifacts * * @return A configured transformer */ public Transformer getTransformer() { final Transformer transformer = new Transformer( createLoggingPrintStream(getLog()::info), createLoggingPrintStream(getLog()::error)); transformer.setOptionDefaults(JakartaTransformer.class, getOptionDefaults()); return transformer; } /** * Gets the source artifacts that should be transformed * * @return an array to artifacts to be transformed */ public Artifact[] getSourceArtifacts() { List artifactList = new ArrayList<>(); if (project.getArtifact() != null && project.getArtifact() .getFile() != null) { artifactList.add(project.getArtifact()); } for (final Artifact attachedArtifact : project.getAttachedArtifacts()) { if (attachedArtifact.getFile() != null) { artifactList.add(attachedArtifact); } } return artifactList.toArray(new Artifact[0]); } private Map getOptionDefaults() { Map optionDefaults = new HashMap<>(); optionDefaults.put(Transformer.AppOption.RULES_RENAMES, isEmpty(rulesRenamesUri) ? "jakarta-renames.properties" : rulesRenamesUri); optionDefaults.put(Transformer.AppOption.RULES_VERSIONS, isEmpty(rulesVersionUri) ? "jakarta-versions.properties" : rulesVersionUri); optionDefaults.put(Transformer.AppOption.RULES_BUNDLES, isEmpty(rulesBundlesUri) ? "jakarta-bundles.properties" : rulesBundlesUri); optionDefaults.put(Transformer.AppOption.RULES_DIRECT, isEmpty(rulesDirectUri) ? "jakarta-direct.properties" : rulesDirectUri); optionDefaults.put(Transformer.AppOption.RULES_MASTER_TEXT, isEmpty(rulesXmlsUri) ? "jakarta-text-master.properties" : rulesXmlsUri); optionDefaults.put(Transformer.AppOption.RULES_PER_CLASS_CONSTANT, isEmpty(rulesPerClassConstantUri) ? "jakarta-per-class-constant-master.properties" : rulesPerClassConstantUri); return optionDefaults; } private PrintStream createLoggingPrintStream(Consumer logConsumer) { try { return new PrintStream(new LoggingOutputStream(logConsumer, MAX_LOG_BUFFER_SIZE), true, StandardCharsets.UTF_8.name()); } catch (UnsupportedEncodingException e) { throw new IllegalStateException("UTF-8 encoding is not supported", e); } } private static final class LoggingOutputStream extends OutputStream { private final Consumer logConsumer; private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); private final int maxBufferSize; private LoggingOutputStream(Consumer logConsumer, int maxBufferSize) { this.logConsumer = logConsumer; this.maxBufferSize = maxBufferSize > 0 ? maxBufferSize : Integer.MAX_VALUE; } @Override public void write(int b) { if (b == '\n') { flushBuffer(); } else if (b != '\r') { buffer.write(b); if (buffer.size() >= this.maxBufferSize) { flushBuffer(); } } } @Override public void flush() { flushBuffer(); } @Override public void close() throws IOException { flushBuffer(); } private void flushBuffer() { if (buffer.size() == 0) { return; } logConsumer.accept(new String(buffer.toByteArray(), StandardCharsets.UTF_8)); buffer.reset(); } } private boolean isEmpty(final String input) { return input == null || input.trim() .length() == 0; } void setProject(MavenProject project) { this.project = project; } void setClassifier(String classifier) { this.classifier = classifier; } MavenProjectHelper getProjectHelper() { return projectHelper; } void setProjectHelper(MavenProjectHelper projectHelper) { this.projectHelper = projectHelper; } void setOverwrite(Boolean overwrite) { this.overwrite = overwrite; } void setOutputDirectory(File outputDirectory) { this.outputDirectory = outputDirectory; } void setAttach(Boolean attach) { this.attach = attach; } } ================================================ FILE: modules/swagger-gradle-plugin/.gitignore ================================================ # Created by https://www.gitignore.io/api/java,gradle,intellij ### 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 ### Java ### # 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* ### 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/java,gradle,intellij .idea/modules # IntelliJ IDEA .idea/ *.iml *.iws *.ipr ================================================ FILE: modules/swagger-gradle-plugin/README.md ================================================ # swagger-gradle-plugin **`swagger-gradle-plugin` supports gradle 3.2 and higher.** ## Jakarta namespace support Since version 2.1.7 Swagger Core supports also Jakarta namespace, with a parallel set of artifacts with `-jakarta` suffix, providing the same functionality as the "standard" `javax` namespace ones. Please check [Wiki](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Getting-started) for more details To have gradle plugin use the `jakarta` namespace artifacts, you need to provide a value to parameter `buildClasspath` In many cases it is sufficient to set it to the `classpath` value, like: `buildClasspath = classpath` Alternatively provide as value a classpath with the following dependencies (replacing the provided [`javax` ones](https://github.com/swagger-api/swagger-core/blob/master/modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java#L16-L25)): * org.apache.commons:commons-lang3:3.20.0 * io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.9 * jakarta.ws.rs:jakarta.ws.rs-api:3.0.0 * jakarta.servlet:jakarta.servlet-api:5.0.0 ## Installation ### Gradle 3.2 and higher ``` plugins { id "io.swagger.core.v3.swagger-gradle-plugin" version "2.2.45" } ``` ### Gradle 1.x and 2.0 **NOTE**: Since version `2.0.10` gradle 1.x and 2.x up to 3.1 are not supported. with versions up to `2.0.9`: ``` buildscript { repositories { maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath "io.swagger.core.v3:swagger-gradle-plugin:2.2.45" } } apply plugin: "io.swagger.core.v3.swagger-gradle-plugin" ``` ## Tasks ### resolve * Resolves project openAPI specification and saves the result in JSON, YAML or both formats. All parameters except `outputFileName`, `outputFormat`, `classpath`, `skip`, `encoding`, `outputDir` and `outputPath` correspond to `swagger` [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties) with same name. #### Example Usage ``` resolve { outputFileName = 'PetStoreAPI' outputFormat = 'JSON' prettyPrint = 'TRUE' classpath = sourceSets.main.runtimeClasspath resourcePackages = ['io.test'] outputDir = file('test') } ``` #### Parameters Parameter | Description | Required | Default --------- | ----------- | --------- | ------- `classpath`|classpath for resources to scan (swagger and deps already included in classpath)|true| `outputDir`|output path where file(s) are saved|true| `outputFileName`|file name (no extension)|false|`openapi` `outputFormat`|file format (`JSON`, `YAML`, `JSONANDYAML`|false|`JSON` `skip`|if `TRUE` skip execution|false|`FALSE` `encoding`|encoding of output file(s)|false| `resourcePackages`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `resourceClasses`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `prettyPrint`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`TRUE` `sortOutput`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE` `alwaysResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE` `skipResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false|`FALSE` `openApiFile`|openapi file to be merged with resolved specification, equivalent to [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties) openAPI|false| `filterClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `readerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `scannerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `readAllResources`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `ignoredRoutes`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `objectMapperProcessorClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `modelConverterClasses`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `contextId`|see [Context](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#context)|false| `outputPath`|**DEPRECATED** output path where file(s) are saved|false| `defaultResponseCode`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `groupsValidationStrategy`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `validatorProcessorClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `openapi31`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `schemaResolution`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| DEFAULT | `openAPIVersion`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| `3.0.1/3.1.0` | **Note** parameter `openApiFile` corresponds to [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties) openAPI. It points to a location of a file in YAML or JSON format representing the input spec that will be merged with the resolved spec. Typically used to add Info section, or any other meta data. An example of such file: ```yaml openapi: 3.0.4 info: version: '1.0' title: Swagger Pet Sample App Config File description: 'This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key special-key to test the authorization filters.' termsOfService: http://swagger.io/terms/ contact: email: apiteam@swagger.io license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html ``` - Since version 2.1.6, `sortOutput` parameter is available, allowing to sort object properties and map keys alphabetically. - Since version 2.1.6, `objectMapperProcessorClass` allows to configure also the ObjectMapper instance used to serialize the resolved OpenAPI - Since version 2.1.9, `alwaysResolveAppPath` parameter is available, allowing to trigger resolving of Application Path from annotation also not in runtime (e.g. using servlet in separate application, or in maven plugin at build time, etc) - Since version 2.2.12, `openapi31` parameter is available, if set to true the resolved spec will be processed into a 3.1.0 specification by resolving according to OAS 3.1 rules - Since version 2.1.15, `skipResolveAppPath` parameter is available, allowing to skip resolving of Application Path from annotation - Since version 2.2.17, `defaultResponseCode` parameter is available, allowing to set the code used when resolving responses with no http status code annotation - Since version 2.2.24, `schemaResolution` parameter is available, allowing to specify how object schemas and object properties within schemas are resolved for OAS 3.0 specification - Since version 2.2.28, `openAPIVersion` parameter is available, allowing to specify the version of the OpenAPI specification to be used for the resolved spec. - Since version 2.2.29, `groupsValidationStrategy` parameter is available, allowing to specify the strategy for resolving Validation annotations (`never`, `always`, `neverIfNoContext`). - Since version 2.2.29, `validatorProcessorClass` parameter is available, allowing to specify a custom validator processor class, implementation of `io.swagger.v3.core.util.ValidatorProcessor`. ================================================ FILE: modules/swagger-gradle-plugin/build.gradle ================================================ // * * * * * * * * * * * * // Plugins // * * * * * * * * * * * * plugins { id 'java-gradle-plugin' // Publishing publicly id 'com.gradle.plugin-publish' version '0.21.0' // Publishing to maven id 'maven-publish' } // * * * * * * * * * * * * // Dependencies // * * * * * * * * * * * * repositories { mavenLocal() mavenCentral() } compileJava { options.release = 8 } dependencies { implementation gradleApi() implementation 'org.apache.commons:commons-lang3:3.20.0' testImplementation gradleTestKit() testImplementation('com.github.tomakehurst:wiremock:2.27.2') { exclude group: 'com.jayway.jsonpath', module: 'json-path' exclude group: 'org.eclipse.jetty', module: 'jetty-server' exclude group: 'org.eclipse.jetty', module: 'jetty-servlet' exclude group: 'org.eclipse.jetty', module: 'jetty-servlets' exclude group: 'org.eclipse.jetty', module: 'jetty-webapp' exclude group: 'org.eclipse.jetty', module: 'jetty-proxy' exclude group: 'commons-codec', module: 'commons-codec' exclude group: 'com.github.jknack', module: 'handlebars' exclude group: 'com.github.jknack', module: 'handlebars-helpers' } testImplementation 'javax.servlet:javax.servlet-api:3.1.0' testImplementation 'com.google.guava:guava:32.1.3-jre' testImplementation 'javax.ws.rs:javax.ws.rs-api:2.1.1' testImplementation "io.swagger.core.v3:swagger-jaxrs2:${project.version}" testImplementation 'org.testng:testng:7.10.2' testImplementation "org.eclipse.jetty:jetty-server:${project.jettyVersion}" testImplementation "org.eclipse.jetty:jetty-servlet:${project.jettyVersion}" testImplementation "org.eclipse.jetty:jetty-servlets:${project.jettyVersion}" testImplementation "org.eclipse.jetty:jetty-webapp:${project.jettyVersion}" testImplementation "org.eclipse.jetty:jetty-proxy:${project.jettyVersion}" testImplementation "org.apache.httpcomponents:httpclient:4.5.14" testImplementation "commons-codec:commons-codec:1.16.0" testImplementation "commons-io:commons-io:2.15.1" testImplementation "org.apache.commons:commons-compress:1.25.0" testImplementation "com.github.jknack:handlebars:4.3.1" testImplementation "com.github.jknack:handlebars-helpers:4.3.1" } // * * * * * * * * * * * * // Project configuration // * * * * * * * * * * * * project.description = 'Gradle Plugin for Swagger core' project.group = 'io.swagger.core.v3' project.ext.name = 'swagger-gradle-plugin' project.ext.pluginId = 'io.swagger.core.v3.swagger-gradle-plugin' project.ext.scm = 'https://github.com/swagger-api/swagger-core.git' project.ext.url = 'https://github.com/swagger-api/swagger-core/tree/master/modules/swagger-gradle-plugin' // Configuration for: java-gradle-plugin gradlePlugin { plugins { swagger { id = project.pluginId implementationClass = 'io.swagger.v3.plugins.gradle.SwaggerPlugin' } } } // * * * * * * * * * * * * // Publishing // * * * * * * * * * * * * // Publishing to plugins.gradle.org // -------------------------------- // Configuration for: com.gradle.plugin-publish pluginBundle { website = project.url vcsUrl = project.scm tags = ['swagger', 'openapi', 'api'] plugins { swagger { displayName = 'Swagger Gradle Plugin ' description = project.description id = project.pluginId } } } test { useTestNG() } publishing { repositories { maven { url mavenLocal().url } } } ================================================ FILE: modules/swagger-gradle-plugin/gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: modules/swagger-gradle-plugin/gradle.properties ================================================ version=2.2.46-SNAPSHOT jettyVersion=9.4.53.v20231009 ================================================ FILE: modules/swagger-gradle-plugin/gradlew ================================================ #!/bin/sh # # Copyright © 2015-2021 the original 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 POSIX generated by Gradle. # # Important for running: # # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is # noncompliant, but you have some other compliant shell such as ksh or # bash, then to run this script, type that shell name before the whole # command line, like: # # ksh Gradle # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # «${var#prefix}», «${var%suffix}», and «$( cmd )»; # * compound commands having a testable exit status, especially «case»; # * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # # (2) This script targets any POSIX shell, so it avoids extensions provided # by Bash, Ksh, etc; in particular arrays are avoided. # # The "traditional" practice of packing multiple parameters into a # space-separated string is a well documented source of bugs and security # problems, so this is (mostly) avoided, by progressively accumulating # options in "$@", and eventually passing that to Java. # # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; # see the in-line comments for details. # # There are tweaks for specific operating systems such as AIX, CygWin, # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. # ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link app_path=$0 # Need this for daisy-chained symlinks. while APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path [ -h "$app_path" ] do ls=$( ls -ld "$app_path" ) link=${ls#*' -> '} case $link in #( /*) app_path=$link ;; #( *) app_path=$APP_HOME$link ;; esac done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # 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 "$*" } >&2 die () { echo echo "$*" echo exit 1 } >&2 # 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 ;; #( MSYS* | 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" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi # Collect all arguments for the java command, stacking in reverse order: # * args from the command line # * the main class name # * -classpath # * -D...appname settings # * --module-path (only if needed) # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) # Now convert the arguments - kludge to limit ourselves to /bin/sh for arg do if case $arg in #( -*) false ;; # don't mess with options #( /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath [ -e "$t" ] ;; #( *) false ;; esac then arg=$( cygpath --path --ignore --mixed "$arg" ) fi # Roll the args list around exactly as many times as the number of # args, so each arg winds up back in the position where it started, but # possibly modified. # # NB: a `for` loop captures its iteration list before it begins, so # changing the positional parameters here affects neither the number of # iterations, nor the values presented in `arg`. shift # remove old arg set -- "$@" "$arg" # push replacement arg done fi # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in # double quotes to make sure that they get re-expanded; and # * put everything else in single quotes, so that it's not re-expanded. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ org.gradle.wrapper.GradleWrapperMain \ "$@" # Stop when "xargs" is not available. if ! command -v xargs >/dev/null 2>&1 then die "xargs is not available" fi # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # # In Bash we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" # # but POSIX shell has neither arrays nor command substitution, so instead we # post-process each arg (as a line of input to sed) to backslash-escape any # character that might be a shell metacharacter, then use eval to reverse # that process (while maintaining the separation between arguments), and wrap # the whole thing up as a single "set" statement. # # This will of course break if any of these variables contains a newline or # an unmatched quote. # eval "set -- $( printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | xargs -n1 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | tr '\n' ' ' )" '"$@"' exec "$JAVACMD" "$@" ================================================ FILE: modules/swagger-gradle-plugin/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=. @rem This is normally unused 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% equ 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% equ 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! set EXIT_CODE=%ERRORLEVEL% if %EXIT_CODE% equ 0 set EXIT_CODE=1 if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: modules/swagger-gradle-plugin/settings.gradle ================================================ rootProject.name = 'swagger-gradle-plugin' ================================================ FILE: modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/SwaggerPlugin.java ================================================ package io.swagger.v3.plugins.gradle; import io.swagger.v3.plugins.gradle.tasks.ResolveTask; import org.gradle.api.Action; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.DependencySet; import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.TaskProvider; public class SwaggerPlugin implements Plugin { public void apply(Project project) { final Configuration config = project.getConfigurations().create("swaggerDeps") .setVisible(false); config.defaultDependencies(new Action() { public void execute(DependencySet dependencies) { dependencies.add(project.getDependencies().create("org.apache.commons:commons-lang3:3.20.0")); dependencies.add(project.getDependencies().create("io.swagger.core.v3:swagger-jaxrs2:2.2.46-SNAPSHOT")); dependencies.add(project.getDependencies().create("javax.ws.rs:javax.ws.rs-api:2.1")); dependencies.add(project.getDependencies().create("javax.servlet:javax.servlet-api:3.1.0")); } }); TaskProvider lazyTask = project.getTasks().register("resolve", ResolveTask.class,task -> { task.buildClasspath.setFrom(config); task.classpath.setFrom(project.getExtensions().findByType(SourceSetContainer.class).getByName("main").getRuntimeClasspath().getFiles()); task.prettyPrint.convention(false); task.readAllResources.convention(true); task.outputFormat.convention(ResolveTask.Format.JSON); task.skip.convention(false); task.encoding.convention("UTF-8"); task.sortOutput.convention(Boolean.FALSE); task.alwaysResolveAppPath.convention(Boolean.FALSE); task.skipResolveAppPath.convention(Boolean.FALSE); task.openAPI31.convention(false); task.convertToOpenAPI31.convention(false); task.outputDir.convention(project.getLayout().getBuildDirectory().dir("swagger")); }); } } ================================================ FILE: modules/swagger-gradle-plugin/src/main/java/io/swagger/v3/plugins/gradle/tasks/ResolveTask.java ================================================ package io.swagger.v3.plugins.gradle.tasks; import org.apache.commons.lang3.StringUtils; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.RegularFileProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; import org.gradle.api.provider.SetProperty; import org.gradle.api.tasks.*; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @CacheableTask public class ResolveTask extends DefaultTask { public enum Format {JSON, YAML, JSONANDYAML} @Input @Optional public final Property outputFileName = getProject().getObjects().property(String.class); @OutputDirectory public final DirectoryProperty outputDir = getProject().getObjects().directoryProperty(); @InputFile @Optional @PathSensitive(PathSensitivity.RELATIVE) public final RegularFileProperty openApiFile = getProject().getObjects().fileProperty(); @Input @Optional public final Property outputFormat = getProject().getObjects().property(Format.class); @Input @Optional public final SetProperty resourcePackages = getProject().getObjects().setProperty(String.class); @Input @Optional public final SetProperty resourceClasses = getProject().getObjects().setProperty(String.class); @Input @Optional public final Property filterClass = getProject().getObjects().property(String.class); @Input @Optional public final Property readerClass = getProject().getObjects().property(String.class); @Input @Optional public final Property scannerClass = getProject().getObjects().property(String.class); @Input @Optional public final Property prettyPrint = getProject().getObjects().property(Boolean.class); @Input @Optional public final Property readAllResources = getProject().getObjects().property(Boolean.class); @Input @Optional public final SetProperty ignoredRoutes = getProject().getObjects().setProperty(String.class); @Classpath @Optional public final ConfigurableFileCollection buildClasspath = getProject().getObjects().fileCollection(); @Classpath public final ConfigurableFileCollection classpath = getProject().getObjects().fileCollection(); /** * Completely skips execution of the task. * * @deprecated if you want to skip the task do not execute it in the first place or remove the task dependency * that causes it to run */ @Deprecated @Input @Optional public final Property skip = getProject().getObjects().property(Boolean.class); @Input @Optional public final Property encoding = getProject().getObjects().property(String.class); /** * @since 2.0.6 */ @Input @Optional public final SetProperty modelConverterClasses = getProject().getObjects().setProperty(String.class); @Input @Optional public final Property objectMapperProcessorClass = getProject().getObjects().property(String.class); @Input @Optional public final Property sortOutput = getProject().getObjects().property(Boolean.class); @Input @Optional public final Property alwaysResolveAppPath = getProject().getObjects().property(Boolean.class); @Input @Optional public final Property skipResolveAppPath = getProject().getObjects().property(Boolean.class); @Input @Optional public final Property contextId = getProject().getObjects().property(String.class); @Input @Optional public final Property openAPI31 = getProject().getObjects().property(Boolean.class); /** * @since 2.2.12 */ @Input @Optional public final Property convertToOpenAPI31 = getProject().getObjects().property(Boolean.class); /** * @since 2.2.24 */ @Input @Optional public final Property schemaResolution = getProject().getObjects().property(String.class); @Input @Optional private Property openAPIVersion = getProject().getObjects().property(String.class);; @Input @Optional public final Property defaultResponseCode = getProject().getObjects().property(String.class); @Input @Optional public final Property validatorProcessorClass = getProject().getObjects().property(String.class); @Input @Optional public final Property groupsValidationStrategy = getProject().getObjects().property(String.class); public Property getOutputFileName() { return outputFileName; } public RegularFileProperty getOpenApiFile() { return openApiFile; } public DirectoryProperty getOutputDir() { return outputDir; } public void setOutputDir(String outputPath) { this.outputDir.set(getProject().file(outputPath)); } public void setOutputFileName(String outputFileName) { this.outputFileName.set(outputFileName); } public void setOpenApiFile(File openApiFile) { this.openApiFile.set(openApiFile); } public ConfigurableFileCollection getClasspath() { return classpath; } public void setClasspath(Iterable classpath) { this.classpath.setFrom(classpath); } public ConfigurableFileCollection getBuildClasspath() { return buildClasspath; } public void setBuildClasspath(Iterable buildClasspath) { this.buildClasspath.setFrom(buildClasspath); } /** * @deprecated Use {@linkplain #outputDir} instead. */ @Deprecated @Internal public Provider getOutputPath() { return outputDir.map(dir -> dir.getAsFile().getPath()); } /** * @deprecated Use {@linkplain #outputDir} instead. */ @Deprecated public void setOutputPath(String outputPath) { this.outputDir.set(getProject().file(outputPath)); } public Property getOutputFormat() { return outputFormat; } public void setOutputFormat(String outputFormat) { this.outputFormat.set(Format.valueOf(outputFormat)); } public void setOutputFormat(Format outputFormat) { this.outputFormat.set(outputFormat); } public SetProperty getResourcePackages() { return resourcePackages; } public void setResourcePackages(Set resourcePackages) { this.resourcePackages.set(resourcePackages); } public SetProperty getModelConverterClasses() { return modelConverterClasses; } public void setModelConverterClasses(Set modelConverterClasses) { this.modelConverterClasses.set(modelConverterClasses); } public SetProperty getResourceClasses() { return resourceClasses; } public void setResourceClasses(Set resourceClasses) { this.resourceClasses.set(resourceClasses); } public Property getFilterClass() { return filterClass; } public void setFilterClass(String filterClass) { this.filterClass.set(filterClass); } public Property getReaderClass() { return readerClass; } public void setReaderClass(String readerClass) { this.readerClass.set(readerClass); } public Property getObjectMapperProcessorClass() { return objectMapperProcessorClass; } /** * @since 2.0.6 */ public void setObjectMapperProcessorClass(String objectMapperProcessorClass) { this.objectMapperProcessorClass.set(objectMapperProcessorClass); } /** * @since 2.2.17 */ public Property getDefaultResponseCode() { return defaultResponseCode; } /** * @since 2.2.17 */ public void setDefaultResponseCode(String defaultResponseCode) { this.defaultResponseCode.set(defaultResponseCode); } /** * @since 2.2.29 */ public Property getValidatorProcessorClass() { return validatorProcessorClass; } /** * @since 2.2.29 */ public void setValidatorProcessorClass(String validatorProcessorClass) { this.validatorProcessorClass.set(validatorProcessorClass); } /** * @since 2.2.29 */ public Property getGroupsValidationStrategy() { return groupsValidationStrategy; } /** * @since 2.2.29 */ public void setGroupsValidationStrategy(String groupsValidationStrategy) { this.groupsValidationStrategy.set(groupsValidationStrategy); } public Property getContextId() { return contextId; } /** * @since 2.0.6 */ public void setContextId(String contextId) { this.contextId.set(contextId); } public Property getScannerClass() { return scannerClass; } public void setScannerClass(String scannerClass) { this.scannerClass.set(scannerClass); } public Property getPrettyPrint() { return prettyPrint; } public void setPrettyPrint(@Nullable String prettyPrint) { setPrettyPrint(prettyPrint == null ? null : Boolean.valueOf(prettyPrint)); } public void setPrettyPrint(@Nullable Boolean prettyPrint) { this.prettyPrint.set(prettyPrint); } public Property getReadAllResources() { return readAllResources; } public void setReadAllResources(Boolean readAllResources) { this.readAllResources.set(readAllResources); ; } public void setReadAllResources(@Nullable String readAllResources) { setReadAllResources(readAllResources == null ? null : Boolean.valueOf(readAllResources)); } public SetProperty getIgnoredRoutes() { return ignoredRoutes; } public void setIgnoredRoutes(Collection ignoredRoutes) { this.ignoredRoutes.set(ignoredRoutes); } public Property getSkip() { return skip; } public void setSkip(Boolean skip) { this.skip.set(skip); } public Property getEncoding() { return encoding; } public void setEncoding(String encoding) { this.encoding.set(encoding); } public Property getSortOutput() { return sortOutput; } public void setSortOutput(Boolean sortOutput) { this.sortOutput.set(sortOutput); } public Property getAlwaysResolveAppPath() { return alwaysResolveAppPath; } public void setAlwaysResolveAppPath(Boolean alwaysResolveAppPath) { this.alwaysResolveAppPath.set(alwaysResolveAppPath); } public void setAlwaysResolveAppPath(@Nullable String alwaysResolveAppPath) { setAlwaysResolveAppPath(alwaysResolveAppPath == null ? null : Boolean.valueOf(alwaysResolveAppPath)); } public Property getSkipResolveAppPath() { return skipResolveAppPath; } /** * @since 2.2.15 */ public void setSkipResolveAppPath(Boolean skipResolveAppPath) { this.skipResolveAppPath.set(skipResolveAppPath); ; } public Property getOpenAPI31() { return openAPI31; } public void setOpenAPI31(Boolean openAPI31) { this.openAPI31.set(openAPI31); } public void setOpenAPI31(@Nullable String openAPI31) { setOpenAPI31(openAPI31 == null ? null : Boolean.valueOf(openAPI31)); } public Property getConvertToOpenAPI31() { return convertToOpenAPI31; } public void setConvertToOpenAPI31(Boolean convertToOpenAPI31) { this.convertToOpenAPI31.set(convertToOpenAPI31); if (Boolean.TRUE.equals(convertToOpenAPI31)) { this.openAPI31.set(Boolean.TRUE); } } public void setConvertToOpenAPI31(@Nullable String convertToOpenAPI31) { setConvertToOpenAPI31(convertToOpenAPI31 == null ? null : Boolean.valueOf(convertToOpenAPI31)); } public Property getSchemaResolution() { return schemaResolution; } public void setSchemaResolution(String schemaResolution) { this.schemaResolution.set(schemaResolution); } public Property getOpenAPIVersion() { return openAPIVersion; } public void setOpenAPIVersion(String openAPIVersion) { this.openAPIVersion.set(openAPIVersion); } @TaskAction public void resolve() throws GradleException { if (skip.getOrElse(false)) { getLogger().warn("You use the deprecated 'skip' property. For better performance prevent the execution instead (for example by calling the `compileJava` task instead)"); getLogger().info("Skipping OpenAPI specification resolution"); return; } getLogger().info("Resolving OpenAPI specification.."); Stream classpathStream = classpath.getFiles().stream().map(f -> { try { return f.toURI().toURL(); } catch (MalformedURLException e) { throw new GradleException( String.format("Could not create classpath for annotations task %s.", getName()), e); } }); Stream buildClasspathStream = buildClasspath.getFiles().stream().map(f -> { try { return f.toURI().toURL(); } catch (MalformedURLException e) { throw new GradleException( String.format("Could not create classpath for annotations task %s.", getName()), e); } }); URL[] urls = Stream.concat(classpathStream, buildClasspathStream) .distinct() .toArray(URL[]::new); //ClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), Thread.currentThread().getContextClassLoader()); try (URLClassLoader classLoader = new URLClassLoader(urls)) { Class swaggerLoaderClass = classLoader.loadClass("io.swagger.v3.jaxrs2.integration.SwaggerLoader"); Object swaggerLoader = swaggerLoaderClass.newInstance(); Method method = null; method = swaggerLoaderClass.getDeclaredMethod("setOutputFormat", String.class); method.invoke(swaggerLoader, outputFormat.get().name()); if (openApiFile.isPresent()) { final File openApiFileHandle = openApiFile.get().getAsFile(); if (openApiFileHandle.exists() && openApiFileHandle.isFile()) { String openapiFileContent = new String(Files.readAllBytes(openApiFileHandle.toPath()), encoding.get()); if (StringUtils.isNotBlank(openapiFileContent)) { method = swaggerLoaderClass.getDeclaredMethod("setOpenapiAsString", String.class); method.invoke(swaggerLoader, openapiFileContent); } } } if (resourcePackages.isPresent() && !resourcePackages.get().isEmpty()) { method = swaggerLoaderClass.getDeclaredMethod("setResourcePackages", String.class); method.invoke(swaggerLoader, resourcePackages.get().stream().map(Object::toString).collect(Collectors.joining(","))); } if (resourceClasses.isPresent() && !resourceClasses.get().isEmpty()) { method = swaggerLoaderClass.getDeclaredMethod("setResourceClasses", String.class); method.invoke(swaggerLoader, resourceClasses.get().stream().map(Object::toString).collect(Collectors.joining(","))); } if (modelConverterClasses.isPresent() && !modelConverterClasses.get().isEmpty()) { method = swaggerLoaderClass.getDeclaredMethod("setModelConverterClasses", String.class); method.invoke(swaggerLoader, modelConverterClasses.get().stream().map(Object::toString).collect(Collectors.joining(","))); } if (ignoredRoutes.isPresent() && !ignoredRoutes.get().isEmpty()) { method = swaggerLoaderClass.getDeclaredMethod("setIgnoredRoutes", String.class); method.invoke(swaggerLoader, ignoredRoutes.get().stream().map(Object::toString).collect(Collectors.joining(","))); } if (filterClass.isPresent() && StringUtils.isNotBlank(filterClass.get())) { method = swaggerLoaderClass.getDeclaredMethod("setFilterClass", String.class); method.invoke(swaggerLoader, filterClass.get()); } if (readerClass.isPresent() && StringUtils.isNotBlank(readerClass.get())) { method = swaggerLoaderClass.getDeclaredMethod("setReaderClass", String.class); method.invoke(swaggerLoader, readerClass.get()); } if (scannerClass.isPresent() && StringUtils.isNotBlank(scannerClass.get())) { method = swaggerLoaderClass.getDeclaredMethod("setScannerClass", String.class); method.invoke(swaggerLoader, scannerClass.get()); } if (contextId.isPresent() && StringUtils.isNotBlank(contextId.get())) { method = swaggerLoaderClass.getDeclaredMethod("setContextId", String.class); method.invoke(swaggerLoader, contextId.get()); } if (objectMapperProcessorClass.isPresent() && StringUtils.isNotBlank(objectMapperProcessorClass.get())) { method = swaggerLoaderClass.getDeclaredMethod("setObjectMapperProcessorClass", String.class); method.invoke(swaggerLoader, objectMapperProcessorClass.get()); } if (defaultResponseCode.isPresent() && StringUtils.isNotBlank(defaultResponseCode.get())) { method = swaggerLoaderClass.getDeclaredMethod("setDefaultResponseCode", String.class); method.invoke(swaggerLoader, defaultResponseCode.get()); } if (validatorProcessorClass.isPresent() && StringUtils.isNotBlank(validatorProcessorClass.get())) { method = swaggerLoaderClass.getDeclaredMethod("setValidatorProcessorClass", String.class); method.invoke(swaggerLoader, validatorProcessorClass.get()); } if (groupsValidationStrategy.isPresent() && StringUtils.isNotBlank(groupsValidationStrategy.get())) { method = swaggerLoaderClass.getDeclaredMethod("setGroupsValidationStrategy", String.class); method.invoke(swaggerLoader, groupsValidationStrategy.get()); } method = swaggerLoaderClass.getDeclaredMethod("setPrettyPrint", Boolean.class); method.invoke(swaggerLoader, prettyPrint.get()); method = swaggerLoaderClass.getDeclaredMethod("setSortOutput", Boolean.class); method.invoke(swaggerLoader, sortOutput.get()); method = swaggerLoaderClass.getDeclaredMethod("setAlwaysResolveAppPath", Boolean.class); method.invoke(swaggerLoader, alwaysResolveAppPath.get()); method = swaggerLoaderClass.getDeclaredMethod("setSkipResolveAppPath", Boolean.class); method.invoke(swaggerLoader, skipResolveAppPath.get()); method = swaggerLoaderClass.getDeclaredMethod("setReadAllResources", Boolean.class); method.invoke(swaggerLoader, readAllResources.get()); if (openAPI31.isPresent() && !openAPI31.get() && convertToOpenAPI31.get()) { throw new GradleException("`convertToOpenAPI31` can't be enabled when `openAPI31` support is explicity disabled"); } if (openAPI31.isPresent()) { method = swaggerLoaderClass.getDeclaredMethod("setOpenAPI31", Boolean.class); method.invoke(swaggerLoader, openAPI31.get()); } if (convertToOpenAPI31.isPresent()) { method = swaggerLoaderClass.getDeclaredMethod("setConvertToOpenAPI31", Boolean.class); method.invoke(swaggerLoader, convertToOpenAPI31.get()); } if (schemaResolution.isPresent()) { method = swaggerLoaderClass.getDeclaredMethod("setSchemaResolution", String.class); method.invoke(swaggerLoader, schemaResolution.get()); } if (openAPIVersion.isPresent()) { method = swaggerLoaderClass.getDeclaredMethod("setOpenAPIVersion", String.class); method.invoke(swaggerLoader, openAPIVersion.get()); } method = swaggerLoaderClass.getDeclaredMethod("resolve"); Map specs = (Map) method.invoke(swaggerLoader); final Path outputFile = outputDir.getAsFile().get().toPath(); if (specs.get("JSON") != null) { Path path = outputFile.resolve(String.format("%s.json", outputFileName.get())); Files.write(path, specs.get("JSON").getBytes(Charset.forName(encoding.get()))); getLogger().debug("Saved openapi to {}", path.toAbsolutePath()); } if (specs.get("YAML") != null) { Path path = outputFile.resolve(String.format("%s.yaml", outputFileName.get())); Files.write(path, specs.get("YAML").getBytes(Charset.forName(encoding.get()))); getLogger().debug("Saved openapi to {}", path.toAbsolutePath()); } } catch (IOException e) { throw new GradleException("Failed to write API definition: " + e.getMessage(), e); } catch (Exception e) { throw new GradleException(e.getMessage(), e); } } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/SwaggerResolveTest.java ================================================ package io.swagger.v3.plugins.gradle; import static java.lang.String.format; import static org.gradle.testkit.runner.TaskOutcome.SUCCESS; import static org.testng.Assert.assertTrue; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.GradleRunner; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; public class SwaggerResolveTest { private Path testProjectDir; private Path buildFile; private Path settingsFile; private Path openapiInputFile; private String outputFile; private String outputDir; @BeforeMethod public void setup() throws IOException { testProjectDir = Files.createTempDirectory("test"); buildFile = Files.createFile(testProjectDir.resolve("build.gradle")); settingsFile = Files.createFile(testProjectDir.resolve("settings.gradle")); openapiInputFile = Files.createFile(testProjectDir.resolve("openapiinput.yaml")); writeFile(openapiInputFile, "openapi: 3.0.1\n" + "servers:\n" + "- url: http://foo\n" + " description: server 1\n" + " variables:\n" + " var1:\n" + " description: var 1\n" + " enum:\n" + " - \"1\"\n" + " - \"2\"\n" + " default: \"2\"\n" + " var2:\n" + " description: var 2\n" + " enum:\n" + " - \"1\"\n" + " - \"2\"\n" + " default: \"2\""); } @Test public void testSwaggerResolveTask() throws IOException { outputDir = testProjectDir.toString() + "/target"; outputFile = testProjectDir.toString() + "/testAPI.json"; //outputDir = "/tmp/a/target"; String resolveTask = "resolve"; String buildFileContent = "plugins {\n" + " id 'java'\n" + " id 'io.swagger.core.v3.swagger-gradle-plugin'\n" + "}\n" + "sourceSets {\n" + " test {\n" + " java {\n" + " srcDirs('" + toNormalizedPath(new File("src/test/java").getAbsolutePath()) + "')\n" + " exclude('**/*Test.java')\n" + " }\n" + " }\n" + "}\n" + "repositories {\n" + " mavenLocal()\n" + " mavenCentral()\n" + "}\n" + "dependencies { \n" + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.46-SNAPSHOT'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + " testImplementation 'org.testng:testng:7.10.2'\n" + "\n" + "\n" + "}\n" + resolveTask + " {\n" + " outputFileName = 'PetStoreAPI'\n" + " outputFormat = 'JSON'\n" + " prettyPrint = 'TRUE'\n" + //" classpath = compileTestJava.outputs.files\n" + " classpath = sourceSets.test.runtimeClasspath\n" + " resourcePackages = ['io.swagger.v3.plugins.gradle.petstore']\n" + " outputPath = \'" + toNormalizedPath(outputDir) + "\'\n" + " filterClass = \'io.swagger.v3.plugins.gradle.resources.MyFilter\'\n" + " openApiFile = file(\'" + toNormalizedPath(openapiInputFile.toAbsolutePath().toString()) + "\')\n" + "}"; String settingsFileContent = "pluginManagement {\n" + " repositories {\n" + " maven {\n" + " url mavenLocal().url\n" + " }\n" + " mavenCentral()\n" + " gradlePluginPortal()\n" + " }\n" + "}\n" + "rootProject.name = 'gradle-test'\n" + "\n"; writeFile(buildFile, buildFileContent); writeFile(settingsFile, settingsFileContent); BuildResult result = GradleRunner.create() .withPluginClasspath() .withProjectDir(testProjectDir.toFile()) .withDebug(true) .withArguments(resolveTask, "--stacktrace", "--info") .forwardOutput() .build(); assertTrue(result.taskPaths(SUCCESS).contains(format(":%s", resolveTask))); assertTrue(new File(outputDir + "/PetStoreAPI.json").exists()); assertTrue(Files.readString(Paths.get(outputDir, "PetStoreAPI.json")).contains("UPDATEDBYFILTER")); } @Test public void testSwaggerResolveWithOAS31OptionTask() throws IOException { outputDir = testProjectDir.toString() + "/target"; outputFile = testProjectDir.toString() + "/testAPI31.json"; //outputDir = "/tmp/a/target"; String resolveTask = "resolve"; String buildFileContent = "plugins {\n" + " id 'java'\n" + " id 'io.swagger.core.v3.swagger-gradle-plugin'\n" + "}\n" + "sourceSets {\n" + " test {\n" + " java {\n" + " srcDirs('" + toNormalizedPath(new File("src/test/java").getAbsolutePath()) + "')\n" + " exclude('**/*Test.java')\n" + " }\n" + " }\n" + "}\n" + "repositories {\n" + " mavenLocal()\n" + " mavenCentral()\n" + "}\n" + "dependencies { \n" + " implementation 'io.swagger.core.v3:swagger-jaxrs2:2.2.46-SNAPSHOT'\n" + " implementation 'javax.ws.rs:javax.ws.rs-api:2.1'\n" + " implementation 'javax.servlet:javax.servlet-api:3.1.0'\n" + " testImplementation 'com.github.tomakehurst:wiremock:2.27.2'\n" + " testImplementation 'org.testng:testng:7.10.2'\n" + "\n" + "\n" + "}\n" + resolveTask + " {\n" + " outputFileName = 'PetStoreAPI31'\n" + " outputFormat = 'JSON'\n" + " prettyPrint = 'TRUE'\n" + //" classpath = compileTestJava.outputs.files\n" + " classpath = sourceSets.test.runtimeClasspath\n" + " resourcePackages = ['io.swagger.v3.plugins.gradle.petstore']\n" + " outputPath = \'" + toNormalizedPath(outputDir) + "\'\n" + " openAPI31 = \'TRUE\'\n" + " convertToOpenAPI31 = \'TRUE\'\n" + " openApiFile = file(\'" + toNormalizedPath(openapiInputFile.toAbsolutePath().toString()) + "\')\n" + "}"; String settingsFileContent = "pluginManagement {\n" + " repositories {\n" + " maven {\n" + " url mavenLocal().url\n" + " }\n" + " mavenCentral()\n" + " gradlePluginPortal()\n" + " }\n" + "}\n" + "rootProject.name = 'gradle-test'\n" + "\n"; writeFile(buildFile, buildFileContent); writeFile(settingsFile, settingsFileContent); BuildResult result = GradleRunner.create() .withPluginClasspath() .withProjectDir(testProjectDir.toFile()) .withDebug(true) .withArguments(resolveTask, "--stacktrace", "--info") .forwardOutput() .build(); assertTrue(result.taskPaths(SUCCESS).contains(format(":%s", resolveTask))); assertTrue(new File(outputDir + "/PetStoreAPI31.json").exists()); byte[] content = Files.readAllBytes(Paths.get(outputDir, "PetStoreAPI31.json")); String strContent = new String(content, StandardCharsets.UTF_8); assertTrue(strContent.contains("\"openapi\" : \"3.0.1\"")); } private static void writeFile(Path destination, String content) throws IOException { try (BufferedWriter output = new BufferedWriter(new FileWriter(destination.toFile()))) { output.write(content); } } private static String toNormalizedPath(String path) { return path.replace("\\", "/"); // necessary on windows } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/EmptyPetResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore; /** * An Empty PetResource Class */ public class EmptyPetResource { } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/PetResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.plugins.gradle.resources.QueryResultBean; import io.swagger.v3.plugins.gradle.resources.data.PetData; import io.swagger.v3.plugins.gradle.resources.exception.NotFoundException; import io.swagger.v3.plugins.gradle.resources.model.Pet; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; @Consumes("application/json") @Path("/pet") @Produces({"application/json", "application/xml"}) public class PetResource { static PetData petData = new PetData(); @GET @Path("/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched"/*, _enum = "range[1,10]"*/, required = true) @PathParam("petId") final Long petId) throws NotFoundException { Pet pet = petData.getPetById(petId); if (null != pet) { return Response.ok().entity(pet).build(); } else { throw new NotFoundException(404, "Pet not found"); } } @POST @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPet( @Parameter(description = "Pet object that needs to be added to the store", required = true) final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodynoannotation") @Consumes({"application/json", "application/xml"}) @Produces({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store no annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetNoAnnotation(final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyid") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer with generic parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByInteger( @Parameter(description = "Pet object that needs to be added to the store", required = true) final int petId) { return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyidnoannotation") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer without parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByIntegerNoAnnotation(final int petId) { return Response.ok().entity("SUCCESS").build(); } @PUT @Operation(summary = "Update an existing pet", responses = { @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found"), @ApiResponse(responseCode = "405", description = "Validation exception")}) public Response updatePet( @Parameter(description = "Pet object that needs to be added to the store", required = true) final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @GET @Path("/findByStatus") @Produces("application/xml") @Operation(summary = "Finds Pets by status", description = "Multiple status values can be provided with comma seperated strings", responses = { @ApiResponse( content = @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))), @ApiResponse( responseCode = "400", description = "Invalid status value" )} ) public Response findPetsByStatus( @Parameter(description = "Status values that need to be considered for filter", required = true) @QueryParam("status") final String status, @BeanParam final QueryResultBean qr ) { return Response.ok(petData.findPetByStatus(status)).build(); } @GET @Path("/findByTags") @Produces("application/json") @Operation(summary = "Finds Pets by tags", description = "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.", responses = { @ApiResponse(description = "Pets matching criteria", content = @Content(schema = @Schema(implementation = Pet.class)) ), @ApiResponse(description = "Invalid tag value", responseCode = "400") }) @Deprecated public Response findPetsByTags( @Parameter(description = "Tags to filter by", required = true) @QueryParam("tags") final String tags) { return Response.ok(petData.findPetByTags(tags)).build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/callback/ComplexCallbackResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class ComplexCallbackResource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com"), @Callback( name = "testCallback2", operation = @Operation( operationId = "getAnSpecificReviews", summary = "get a review", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( implementation = User.class)))), callbackUrlExpression = "http://www.url2.com") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/complexcallback") public String simpleGet(@Parameter(description = "idParam", schema = @Schema(implementation = User.class)) @QueryParam("id") final String id) { return null; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/callback/MultipleCallbacksTestWithOperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class MultipleCallbacksTestWithOperationResource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com"), @Callback(name = "testCallback2", operation = @Operation(), callbackUrlExpression = "http://$request.query.url") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/multiplecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/callback/RepeatableCallbackResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class RepeatableCallbackResource { @Callback(name = "testCallback", operation = @Operation(), callbackUrlExpression = "http://$requests.query.url") @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com") @Callback(name = "testCallback2", operation = @Operation(), callbackUrlExpression = "http://$request.query.url") @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/repeatablecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/callback/SimpleCallbackWithOperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class SimpleCallbackWithOperationResource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/simplecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/example/ExamplesResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.example; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.POST; import javax.ws.rs.Path; /** * Examples Resource Scenario */ public class ExamplesResource { @Path("/example") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(name = "Schema", description = "Schema", example = "Subscription example"), style = ParameterStyle.SIMPLE, example = "example", examples = { @ExampleObject(name = "subscriptionId_1", value = "12345", summary = "Subscription number 12345", externalValue = "Subscription external value 1"), @ExampleObject(name = "subscriptionId_2", value = "54321", summary = "Subscription number 54321", externalValue = "Subscription external value 2") }) }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example" ), examples = { @ExampleObject(name = "Default Response", value = "SubscriptionResponse", summary = "Subscription Response Example", externalValue = "Subscription Response value 1") } )) }) public SubscriptionResponse subscribe(@RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example"), examples = { @ExampleObject(name = "Default Request", value = "SubscriptionRequest", summary = "Subscription Request Example", externalValue = "Subscription Request Value") })) User user) { return null; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/example/SubscriptionResponse.java ================================================ package io.swagger.v3.plugins.gradle.petstore.example; public class SubscriptionResponse { public String subscriptionId; } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/link/LinksResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.link; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with Links */ public class LinksResource { @Path("/links") @Operation(operationId = "getUserWithAddress", responses = { @ApiResponse(description = "test description", content = @Content(mediaType = "*/*", schema = @Schema(ref = "#/components/schemas/User")), links = { @Link( name = "address", operationId = "getAddress", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")), @Link( name = "user", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) })} ) @GET public String getUser(@QueryParam("userId")final String userId) { return null; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/openapidefintion/OpenAPIDefinitionResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.openapidefintion; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.info.Contact; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.servers.ServerVariable; import io.swagger.v3.oas.annotations.tags.Tag; /** * OpenAPIDefinition Example */ @OpenAPIDefinition( info = @Info( title = "Pet Resource Example", version = "2.0", description = "API Definition", termsOfService = "Terms of service", license = @License(name = "Apache 2.0", url = "http://foo.bar"), contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com") ), tags = { @Tag(name = "Tag 1", description = "desc 1", externalDocs = @ExternalDocumentation(description = "docs desc")), @Tag(name = "Tag 2", description = "desc 2", externalDocs = @ExternalDocumentation(description = "docs desc 2")), @Tag(name = "Tag 3") }, externalDocs = @ExternalDocumentation(description = "definition docs desc"), security = { @SecurityRequirement(name = "req 1", scopes = {"a", "b"}), @SecurityRequirement(name = "req 2", scopes = {"b", "c"}) }) public class OpenAPIDefinitionResource { public void foo() { } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/AnnotatedSameNameOperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Default Operation without Annotation */ public class AnnotatedSameNameOperationResource { @Path("/sameOperationName") @GET @Operation(description = "Same Operation Name") public String getUser() { return new String(); } @Path("//sameOperationName") @DELETE @Operation(description = "Same Operation Name Duplicated") public String getUser(final String id) { return new String(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/ExternalDocumentationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.plugins.gradle.resources.exception.NotFoundException; import io.swagger.v3.plugins.gradle.resources.model.Pet; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; /** * Resource with Operations Examples */ public class ExternalDocumentationResource { @GET @Path("/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions", operationId = "petId", externalDocs = @ExternalDocumentation(description = "External in Operation", url = "http://url.me")) @ExternalDocumentation(description = "External Annotation Documentation", url = "http://url.me") public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched", required = true) @PathParam("petId") Long petId) throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/FullyAnnotatedOperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.plugins.gradle.resources.exception.NotFoundException; import io.swagger.v3.plugins.gradle.resources.model.Pet; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; /** * Resource with Operations Examples */ public class FullyAnnotatedOperationResource { @GET @Path("/fullyannotatedoperation/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions", operationId = "petId", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched", required = true) @PathParam("petId")final Long petId) throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/HiddenOperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.plugins.gradle.resources.model.Pet; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Hidden Operation */ public class HiddenOperationResource { @Path("/hiddenbyflag") @GET @Operation(operationId = "Pets", description = "Pets Example", hidden = true) public Pet getPet() { return new Pet(); } @Path("/hiddenbyannotation") @GET @Operation(operationId = "Users", description = "Users Example") @Hidden public User getUser() { return new User(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/InterfaceResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; /** * Interface resource */ public interface InterfaceResource { @GET @Path("/interfaceoperation/{petId}") @Operation(summary = "Find pet by ID Operation in Parent", description = "Returns a pet in Parent" ) Response getPetById(@Parameter(description = "ID of pet that needs to be fetched", required = true) @PathParam("petId") final Long petId); } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/NotAnnotatedSameNameOperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Default Operation without Annotation */ public class NotAnnotatedSameNameOperationResource { @Path("/notannotatedoperation") @GET public String getUser() { return new String(); } @Path("/notannotatedoperationduplicated") @GET public String getUser(final String id) { return new String(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/OperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.plugins.gradle.resources.model.Pet; import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.NotFoundException; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; /** * Resource with Complete Operations Examples */ public class OperationResource implements InterfaceResource { @Override @Operation(summary = "Find pet by ID Operation in SubResource", description = "Returns a pet in SubResource" ) public Response getPetById(final Long petId) { return Response.ok().entity(new Pet()).build(); } @GET @Path("/operationsresource") @Operation(summary = "Find pet by ID", description = "combinatedfullyannotatedoperation/{petId}", operationId = "petId", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched", required = true) @QueryParam("petId") final Long petId, final String message) throws NotFoundException { return Response.ok().entity(new Pet()).build(); } @Path("/operationsresource") @POST public String getUser(final String id) { return new String(); } @Path("/operationsresource") @PUT @Operation(operationId = "combinated sameOperationName", description = "combinatedsameOperationName") public String getPerson() { return new String(); } @Path("/operationsresource") @HEAD @Operation(operationId = "combinatedsameOperationNameDuplicated", description = "combinatedsameOperationNameDuplicated") public String getPerson(final String id) { return new String(); } @Path("/operationsresource2") @GET public String getUser() { return new String(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/OperationWithoutAnnotationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Default Operation without Annotation */ public class OperationWithoutAnnotationResource { @Path("/operationwithouannotation") @GET public String getUser() { return new String(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/ServerOperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.plugins.gradle.resources.model.Pet; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Hidden Operation */ public class ServerOperationResource { @Path("/serversoperation") @GET @Operation(operationId = "Pets", description = "Pets Example", servers = { @Server(description = "server 2", url = "http://foo2") } ) public Pet getPet() { return new Pet(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/operation/SubResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.operation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.plugins.gradle.resources.model.Pet; import javax.ws.rs.core.Response; /** * SubResource */ public class SubResource implements InterfaceResource { @Override @Operation(summary = "Find pet by ID Operation in SubResource", description = "Returns a pet in SubResource" ) public Response getPetById(final Long petId) { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/ArraySchemaResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; public class ArraySchemaResource { @Path("/arrayschema") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) ), }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersResource.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersResource.SubscriptionResponse subscribe() { return null; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/ComplexParameterResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a multiple annotated. */ public class ComplexParameterResource { @Parameter(description = "Phone definied in Field") private String phone; public ComplexParameterResource(@Parameter(description = "phone Param", name = "phone") final String phone) { this.phone = phone; } @GET @Path("/complexparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam") @QueryParam("id") final String id, final String name, @QueryParam("lastName") final String lastName, @Parameter(description = "address", schema = @Schema(implementation = User.class)) @QueryParam("address") final String address) { return new User(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/ComplexParameterWithOperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a multiple annotated. */ public class ComplexParameterWithOperationResource { @Parameter(description = "Phone definied in Field") private String phone; public ComplexParameterWithOperationResource(@Parameter(description = "phone Param", name = "phone") final String phone) { this.phone = phone; } @GET @Path("/complexparameter") @Operation(operationId = "create User", parameters = { @Parameter(description = "Phone", name = "phone", in = ParameterIn.PATH) }) public User findUser(@Parameter(description = "idParam") @QueryParam("id") final String id, final String name, @QueryParam("lastName") final String lastName, @Parameter(description = "address", schema = @Schema(implementation = User.class)) @QueryParam("address") final String address) { return new User(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/MultipleNotAnnotatedParameter.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.POST; import javax.ws.rs.Path; /** * Class with a multiple not annotated parameter. */ public class MultipleNotAnnotatedParameter { @POST @Path("/multiplenoannotatedparameter") @Operation(operationId = "create User") public void createUser(final String id, final String name) { } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/OpenAPIJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs and open api annotation. */ public class OpenAPIJaxRSAnnotatedParameter { @GET @Path("/openapijaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam") @QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/OpenAPIWithContentJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs and open api annotation. */ public class OpenAPIWithContentJaxRSAnnotatedParameter { @GET @Path("/openapiwithcontentjaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam", content = @Content(schema = @Schema(description = "Id Schema Definition", required = true, name = "id"))) @QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/OpenAPIWithImplementationJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs and open api annotation. */ public class OpenAPIWithImplementationJaxRSAnnotatedParameter { @GET @Path("/openapiwithimplementationjaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam", schema = @Schema(implementation = User.class)) @QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/ParametersResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Resource with some Parameters examples */ public class ParametersResource { @Path("/parameters") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(implementation = RepeatableParametersResource.SubscriptionResponse.class), style = ParameterStyle.SIMPLE), @Parameter(in = ParameterIn.QUERY, name = "formId", required = true, example = "Example"), @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema(implementation = SubscriptionResponse.class)), @Parameter(in = ParameterIn.QUERY, name = "explodeTrue", required = true, explode = Explode.TRUE, schema = @Schema(implementation = SubscriptionResponse.class)), @Parameter(in = ParameterIn.QUERY, name = "explodeAvoiding", required = true, explode = Explode.TRUE, schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY )), @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = SubscriptionResponse.class), uniqueItems = true ) , schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY), content = @Content(schema = @Schema(type = "number", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY)) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = SubscriptionResponse.class), uniqueItems = true ) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation2", required = true, explode = Explode.TRUE, schema = @Schema(implementation = SubscriptionResponse.class)) }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public SubscriptionResponse subscribe(@Parameter(description = "idParam") @QueryParam("id") final String id) { return null; } static class SubscriptionResponse { public String subscriptionId; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/RepeatableParametersResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; public class RepeatableParametersResource { @Path("/repeatableparameter") @POST @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), style = ParameterStyle.SIMPLE) @Parameter(in = ParameterIn.QUERY, name = "formId", required = true, example = "Example") @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) @Parameter(in = ParameterIn.QUERY, name = "explodeTrue", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) @Parameter(in = ParameterIn.QUERY, name = "explodeAvoiding", required = true, explode = Explode.TRUE, schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY )) @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) , schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY), content = @Content(schema = @Schema(type = "number", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY)) ) @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) ) @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation2", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersResource.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersResource.SubscriptionResponse subscribe() { return null; } static class SubscriptionResponse { public String subscriptionId; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/SingleJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs. */ public class SingleJaxRSAnnotatedParameter { @GET @Path("/singlejaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/parameter/SingleNotAnnotatedParameter.java ================================================ package io.swagger.v3.plugins.gradle.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Class with a single not annotated parameter. */ public class SingleNotAnnotatedParameter { @GET @Path("/singlenoannotatedparameter") @Operation(operationId = "create User") public User findUser(final String id) { return new User(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/requestbody/RequestBodyMethodPriorityResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.requestbody; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with RequestBody inside Operation and another in Method */ public class RequestBodyMethodPriorityResource { @POST @Path("/requestbodymethodpriority") @Operation(summary = "Create user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "Inside Operation")) @RequestBody(description = "Created user object on Method", required = true, content = @Content( schema = @Schema(implementation = User.class))) public Response methodWithRequestBodyAndTwoParameters(final User user) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/requestbody/RequestBodyParameterPriorityResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.requestbody; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with RequestBody inside Operation and another in Method */ public class RequestBodyParameterPriorityResource { @POST @Path("/requestbodyparameterpriority") @Operation(summary = "Create user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "Inside Operation")) @RequestBody(description = "On method") public Response methodWithRequestBodyAndTwoParameters( @RequestBody(description = "Created user object inside Parameter", required = true, content = @Content( schema = @Schema(implementation = User.class)))final User user) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/requestbody/RequestBodyResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.requestbody; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.plugins.gradle.resources.model.Pet; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; /** * Resource with RequestBody examples */ public class RequestBodyResource { @GET @Path("/methodWithRequestBodyWithoutContent") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyWithoutContent( @RequestBody(description = "Created user object", required = true) final User user) { return Response.ok().entity("").build(); } @GET @Path("/methodWithRequestBodyWithoutContentWithoutImplementation") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyWithoutContentWithoutImplementation( @RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema(name = "User", description = "User description", example = "User Description", required = true))) final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithRequestBodyAndTwoParameters") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyAndTwoParameters( @RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema(implementation = User.class))) final User user, @QueryParam("name") final String name, @QueryParam("code") final String code) { return Response.ok().entity("").build(); } @PUT @Path("/methodWithRequestBodyWithoutAnnotation") @Operation(summary = "Modify user", description = "Modifying user.") public Response methodWithRequestBodyWithoutAnnotation( final User user) { return Response.ok().entity("").build(); } @DELETE @Path("/methodWithoutRequestBodyAndTwoParameters") @Operation(summary = "Delete user", description = "This can only be done by the logged in user.") public Response methodWithoutRequestBodyAndTwoParameters( @QueryParam("name") final String name, @QueryParam("code") final String code) { return Response.ok().entity("").build(); } @PUT @Path("/methodWithRequestBodyWithoutAnnotationAndTwoConsumes") @Operation(summary = "Modify pet", description = "Modifying pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithRequestBodyWithoutAnnotationAndTwoConsumes( final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes") @Operation(summary = "Create pet", description = "Creating pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes( final Pet pet, final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithTwoRequestBodyWithAnnotationAndTwoConsumes") @Operation(summary = "Create pet", description = "Creating pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithTwoRequestBodyWithAnnotationAndTwoConsumes( final @RequestBody(description = "Request Body Pet") Pet pet, @RequestBody(description = "Request Body User") final User user) { return Response.ok().entity("").build(); } @DELETE @Path("/methodWithOneSimpleRequestBody") @Operation(summary = "Delete pet", description = "Deleting pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithOneSimpleRequestBody(final int id) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/responses/ComplexResponseResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.plugins.gradle.resources.exception.NotFoundException; import io.swagger.v3.plugins.gradle.resources.model.Pet; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource with some responses */ public class ComplexResponseResource { @GET @Path("/complexresponse") @Operation(summary = "Find pets", description = "Returns the Pets", responses = { @ApiResponse(description = "Response inside Operation", responseCode = "200", content = @Content(schema = @Schema(implementation = Pet.class))), @ApiResponse(description = "Default Pet", content = @Content(schema = @Schema(name = "Default Pet", description = "Default Pet", required = true, example = "New Pet"))) }) @ApiResponse(responseCode = "404", description = "Couldn't find pet") public Pet getPets() throws NotFoundException { return new Pet(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/responses/ImplementationResponseResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource with a Response at Method Level */ public class ImplementationResponseResource { @GET @Path("/implementationresponse") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output object", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = { @Content( mediaType = "application/json", schema = @Schema( implementation = SampleResponseSchema.class) ), @Content( mediaType = "application/json", schema = @Schema( implementation = SecondSampleResponseSchema.class) ) } ), @ApiResponse( responseCode = "400", description = "boo", content = @Content( mediaType = "*/*", schema = @Schema(implementation = GenericError.class) ) ) } ) public void getResponses() { } static class SampleResponseSchema { @Schema(description = "the user id") private String id; } static class SecondSampleResponseSchema { @Schema(description = "the user id") private String id; } static class GenericError { private int code; private String message; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/responses/MethodResponseResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.plugins.gradle.resources.exception.NotFoundException; import io.swagger.v3.plugins.gradle.resources.model.Pet; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with a Response at Method Level */ public class MethodResponseResource { @GET @Path("/responseinmethod") @Operation(summary = "Find pets", description = "Returns the Pets") @ApiResponse(responseCode = "200", description = "Status OK") public Response getPets() throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/responses/NoImplementationResponseResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Resource with a Response at Method Level */ public class NoImplementationResponseResource { @Path("/noimplementationresponseresource") @Operation(operationId = "getUser", responses = { @ApiResponse(description = "test description", responseCode = "400", links = { @Link( name = "user", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) }), @ApiResponse(description = "200 description", responseCode = "200", links = { @Link( name = "pet", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) }) } ) @GET public User getUser(@QueryParam("userId") final String userId) { return null; } static class User { private String id; private String username; public String getId() { return id; } public void setId(final String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(final String username) { this.username = username; } } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/responses/NoResponseResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.plugins.gradle.resources.exception.NotFoundException; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource with a Response at Method Level */ public class NoResponseResource { @GET @Path("/noresponse") @Operation(summary = "Find pets", description = "Returns the Pets") public User getPets() throws NotFoundException { return new User(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/responses/OperationResponseResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.plugins.gradle.resources.exception.NotFoundException; import io.swagger.v3.plugins.gradle.resources.model.User; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with the response in the Operation Annotation */ public class OperationResponseResource { @GET @Path("/responseinoperation") @Operation(summary = "Find Users", description = "Returns the Users", responses = {@ApiResponse(responseCode = "200", description = "Status OK")}) public Response getUsers() throws NotFoundException { return Response.ok().entity(new User()).build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/responses/PriorityResponseResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.plugins.gradle.resources.exception.NotFoundException; import io.swagger.v3.plugins.gradle.resources.model.Pet; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with a Response at Method Level and Operation Level. */ public class PriorityResponseResource { @GET @Path("/priorityresponses") @Operation(summary = "Find pets", description = "Returns the Pets", responses = {@ApiResponse(responseCode = "200", description = "Inside Operation Response")}) @ApiResponse(responseCode = "200", description = "Inside Method Operation") public Response getPets() throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/security/SecurityResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.security; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.security.OAuthFlow; import io.swagger.v3.oas.annotations.security.OAuthFlows; import io.swagger.v3.oas.annotations.security.OAuthScope; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityScheme; import javax.ws.rs.GET; import javax.ws.rs.PATCH; import javax.ws.rs.PUT; import javax.ws.rs.Path; @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, description = "myOauthSecurity Description", flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "http://x.com", scopes = @OAuthScope( name = "write:pets", description = "modify pets in your account")) ) ) @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) @SecurityRequirement(name = "myOauth2Security", scopes = {"write:pets"} ) @Path("/security") public class SecurityResource { @GET @Operation(operationId = "Operation Id", description = "description") @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) public void getSecurity() { } @PATCH @Operation(operationId = "Operation Id 2", description = "description 2") @SecurityRequirement(name = "security_key2", scopes = {"write:pets", "read:pets"} ) public void getSecurity2() { } @PUT @Operation(operationId = "Operation Id 3", description = "description 3", security = @SecurityRequirement(name = "security_key3", scopes = {"write:pets", "read:pets"} )) public void setSecurity(String security) { } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/tags/CompleteTagResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @OpenAPIDefinition(tags = { @Tag(name = "Definition First Tag"), @Tag(name = "Definition Second Tag full", description = "desc definition") }) @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Fifth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Sixth Tag") public class CompleteTagResource { @GET @Path("/completetags") @Operation(tags = {"Example Tag", "Second Tag"}) @Tag(name = "Third Tag") @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc", externalDocs = @ExternalDocumentation(description = "docs desc")) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/tags/TagClassResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.tags.Tag; /** * Class with Tag Annotations at Class level */ @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Fifth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Sixth Tag") public class TagClassResource { } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/tags/TagMethodResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; public class TagMethodResource { @GET @Path("/tagsinmethod") @Tag(name = "Third Tag") @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc", externalDocs = @ExternalDocumentation(description = "docs desc")) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/tags/TagOpenAPIDefinitionResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.tags; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.tags.Tag; /** * Tag in the OpenAPIDefinition annotation */ @OpenAPIDefinition(tags = { @Tag(name = "Definition First Tag"), @Tag(name = "Definition Second Tag full", description = "desc definition") }) public class TagOpenAPIDefinitionResource { } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/petstore/tags/TagOperationResource.java ================================================ package io.swagger.v3.plugins.gradle.petstore.tags; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with a Tag at Operation Level */ public class TagOperationResource { @GET @Path("/tagoperation") @Operation(tags = {"Example Tag", "Second Tag"}) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/MyFilter.java ================================================ package io.swagger.v3.plugins.gradle.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.Map; import java.util.Optional; public class MyFilter extends AbstractSpecFilter { private static Logger LOGGER = LoggerFactory.getLogger(MyFilter.class); @Override public Optional filterOpenAPI( OpenAPI openAPI, Map> params, Map cookies, Map> headers) { openAPI.getInfo().setTitle("UPDATEDBYFILTER"); return Optional.of(openAPI); // some processing //return super.filterOpenAPI(openAPI, params, cookies, headers); } @Override public Optional filterOperation( Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { // some processing return Optional.of(operation); } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/QueryResultBean.java ================================================ package io.swagger.v3.plugins.gradle.resources; import javax.ws.rs.QueryParam; public class QueryResultBean { @QueryParam("skip") private Integer skip; @QueryParam("limit") private Integer limit; public Integer getSkip() { return skip; } public void setSkip(Integer skip) { this.skip = skip; } public Integer getLimit() { return limit; } public void setLimit(Integer limit) { this.limit = limit; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/data/PetData.java ================================================ package io.swagger.v3.plugins.gradle.resources.data; import io.swagger.v3.plugins.gradle.resources.model.Category; import io.swagger.v3.plugins.gradle.resources.model.Pet; import io.swagger.v3.plugins.gradle.resources.model.Tag; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class PetData { static List pets = new ArrayList(); static List categories = new ArrayList(); static { categories.add(createCategory(1, "Dogs")); categories.add(createCategory(2, "Cats")); categories.add(createCategory(3, "Rabbits")); categories.add(createCategory(4, "Lions")); pets.add(createPet(1, categories.get(1), "Cat 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(2, categories.get(1), "Cat 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "available")); pets.add(createPet(3, categories.get(1), "Cat 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "pending")); pets.add(createPet(4, categories.get(0), "Dog 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(5, categories.get(0), "Dog 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "sold")); pets.add(createPet(6, categories.get(0), "Dog 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "pending")); pets.add(createPet(7, categories.get(3), "Lion 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(8, categories.get(3), "Lion 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "available")); pets.add(createPet(9, categories.get(3), "Lion 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "available")); pets.add(createPet(10, categories.get(2), "Rabbit 1", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "available")); } public Pet getPetById(long petId) { for (Pet pet : pets) { if (pet.getId() == petId) { return pet; } } return null; } public List findPetByStatus(String status) { String[] statues = status.split(","); List result = new ArrayList(); for (Pet pet : pets) { for (String s : statues) { if (s.equals(pet.getStatus())) { result.add(pet); } } } return result; } public List findPetByCategory(Category category) { return pets.stream().filter(pet -> category.equals(pet.getCategory())).collect(Collectors.toList()); } public List findPetByTags(String tags) { String[] tagList = tags.split(","); List result = new ArrayList(); for (Pet pet : pets) { if (null != pet.getTags()) { for (Tag tag : pet.getTags()) { for (String tagListString : tagList) { if (tagListString.equals(tag.getName())) { result.add(pet); } } } } } return result; } public void addPet(Pet pet) { if (pets.size() > 0) { for (int i = pets.size() - 1; i >= 0; i--) { if (pets.get(i).getId() == pet.getId()) { pets.remove(i); } } } pets.add(pet); } static Pet createPet(long id, Category cat, String name, String[] urls, String[] tags, String status) { Pet pet = new Pet(); pet.setId(id); pet.setCategory(cat); pet.setName(name); if (null != urls) { List urlObjs = new ArrayList(); for (String urlString : urls) { urlObjs.add(urlString); } pet.setPhotoUrls(urlObjs); } List tagObjs = new ArrayList(); int i = 0; if (null != tags) { for (String tagString : tags) { i = i + 1; Tag tag = new Tag(); tag.setId(i); tag.setName(tagString); tagObjs.add(tag); } } pet.setTags(tagObjs); pet.setStatus(status); return pet; } static Category createCategory(long id, String name) { Category category = new Category(); category.setId(id); category.setName(name); return category; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/data/UserData.java ================================================ package io.swagger.v3.plugins.gradle.resources.data; import io.swagger.v3.plugins.gradle.resources.model.User; import java.util.ArrayList; import java.util.List; public class UserData { static List users = new ArrayList(); static { users.add(createUser(1, "user1", "first name 1", "last name 1", "email1@test.com", "123-456-7890", 1)); users.add(createUser(2, "user2", "first name 2", "last name 2", "email2@test.com", "123-456-7890", 2)); users.add(createUser(3, "user3", "first name 3", "last name 3", "email3@test.com", "123-456-7890", 3)); users.add(createUser(4, "user4", "first name 4", "last name 4", "email4@test.com", "123-456-7890", 1)); users.add(createUser(5, "user5", "first name 5", "last name 5", "email5@test.com", "123-456-7890", 2)); users.add(createUser(6, "user6", "first name 6", "last name 6", "email6@test.com", "123-456-7890", 3)); users.add(createUser(7, "user7", "first name 7", "last name 7", "email7@test.com", "123-456-7890", 1)); users.add(createUser(8, "user8", "first name 8", "last name 8", "email8@test.com", "123-456-7890", 2)); users.add(createUser(9, "user9", "first name 9", "last name 9", "email9@test.com", "123-456-7890", 3)); users.add(createUser(10, "user10", "first name 10", "last name 10", "email10@test.com", "123-456-7890", 1)); users.add(createUser(11, "user?10", "first name ?10", "last name ?10", "email101@test.com", "123-456-7890", 1)); } public User findUserByName(String username) { for (User user : users) { if (user.getUsername().equals(username)) { return user; } } return null; } public void addUser(User user) { if (users.size() > 0) { for (int i = users.size() - 1; i >= 0; i--) { if (users.get(i).getUsername().equals(user.getUsername())) { users.remove(i); } } } users.add(user); } public boolean removeUser(String username) { if (users.size() > 0) { for (int i = users.size() - 1; i >= 0; i--) { if (users.get(i).getUsername().equals(username)) { users.remove(i); return true; } } } return false; } private static User createUser(long id, String username, String firstName, String lastName, String email, String phone, int userStatus) { User user = new User(); user.setId(id); user.setUsername(username); user.setFirstName(firstName); user.setLastName(lastName); user.setEmail(email); user.setPassword("XXXXXXXXXXX"); user.setPhone(phone); user.setUserStatus(userStatus); return user; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/exception/ApiException.java ================================================ package io.swagger.v3.plugins.gradle.resources.exception; public class ApiException extends Exception { private int code; public ApiException(int code, String msg) { super(msg); this.code = code; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/exception/NotFoundException.java ================================================ package io.swagger.v3.plugins.gradle.resources.exception; public class NotFoundException extends ApiException { private int code; public NotFoundException(int code, String msg) { super(code, msg); this.code = code; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/Category.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Category") public class Category { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } public Category() { } public Category(String name) { this.name = name; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/CustomGenerator.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerators; public class CustomGenerator extends ObjectIdGenerators.PropertyGenerator { private static final long serialVersionUID = 1L; protected CustomGenerator(Class scope) { super(scope); } @Override public ObjectIdGenerator forScope(Class scope) { return null; } @Override public ObjectIdGenerator newForSerialization(Object context) { return null; } @Override public IdKey key(Object key) { return null; } @Override public Object generateId(Object forPojo) { return null; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/ExtensionUser.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "User") @Schema( description = "User", extensions = { @Extension(name = "x-user", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "user-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) public class ExtensionUser { private long id; private String username; private String firstName; private String lastName; private String email; private String password; private String phone; private int userStatus; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "firstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement(name = "lastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone") public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @XmlElement(name = "userStatus") //@Schema(description = "User Status", type = "string", allowableValues = {"1-registered", "2-active", "3-closed"}) @Schema( description = "User Status", allowableValues = "1-registered,2-active,3-closed", extensions = { @Extension(name = "x-userStatus", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "userStatus-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/JacksonBean.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonValue; public class JacksonBean { private String id; private String ignored; private StringValueBean bean; private NotFoundModel model; private NotFoundModel model2; @JsonIgnore public String getIgnored() { return ignored; } public void setIgnored(String ignored) { this.ignored = ignored; } public void setId(String id) { this.id = id; } public void setModel(NotFoundModel model) { this.model = model; } public StringValueBean getBean() { return bean; } public void setBean(StringValueBean bean) { this.bean = bean; } @JsonProperty("identity") public String getId() { return id; } @JsonUnwrapped public NotFoundModel getModel() { return model; } @JsonUnwrapped(prefix = "pre", suffix = "suf") public NotFoundModel getModel2() { return model2; } public void setModel2(NotFoundModel model2) { this.model2 = model2; } public static class StringValueBean { private final String value; @JsonCreator public StringValueBean(String value) { this.value = value; } @JsonValue public String getValue() { return value; } } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/ListOfStringsBeanParam.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import javax.ws.rs.QueryParam; import java.util.List; public class ListOfStringsBeanParam { @QueryParam(value = "listOfStrings") private List list; public List getList() { return list; } public void setList(List list) { this.list = list; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/ModelWithJsonIdentity.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.ObjectIdGenerators; public class ModelWithJsonIdentity { @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") @JsonProperty("PropertyGeneratorAsId") public SourceDefinition1 testPropertyGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") @JsonProperty("PropertyGeneratorAsProperty") public SourceDefinition1 testPropertyGeneratorAsProperty; public class SourceDefinition1 { public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "driverId") @JsonProperty("ChangedPropertyName") public SourceDefinition2 testChangedPropertyName; @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "driverId") @JsonProperty("ChangedPropertyName2") public SourceDefinition2 testChangedPropertyName2; static public class SourceDefinition2 { @JsonProperty("driverId") public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class) @JsonProperty("SourceWithoutPropertyAsId") public SourceDefinition3 testWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class) @JsonProperty("SourceWithoutPropertyAsProperty") public SourceDefinition3 testWithoutPropertyAsProperty; public class SourceDefinition3 { @JsonProperty("driverId") public String driver; public String name; @JsonProperty("@id") public String id; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "testName1") @JsonProperty("IntSequenceGeneratorAsId") public SourceDefinition4 testIntSequenceGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "testName2") @JsonProperty("IntSequenceGeneratorAsProperty") public SourceDefinition4 testIntSequenceGeneratorAsProperty; public class SourceDefinition4 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) @JsonProperty("IntSequenceWithoutPropertyAsId") public SourceDefinition5 testIntSequenceWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) @JsonProperty("IntSequenceWithoutPropertyAsProperty") public SourceDefinition5 testIntSequenceWithoutPropertyAsProperty; public class SourceDefinition5 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "UUID1") @JsonProperty("UUIDGeneratorAsId") public SourceDefinition6 testUUIDGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "UUID2") @JsonProperty("UUIDGeneratorAsProperty") public SourceDefinition6 testUUIDGeneratorAsProperty; public class SourceDefinition6 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class) @JsonProperty("UUIDGeneratorWithoutPropertyAsId") public SourceDefinition7 testUUIDGeneratorWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class) @JsonProperty("UUIDGeneratorWithoutPropertyAsProperty") public SourceDefinition7 testUUIDGeneratorWithoutPropertyAsProperty; public class SourceDefinition7 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.None.class, property = "testGeneratorsNone") @JsonProperty("GeneratorsNone") public SourceDefinition8 testGeneratorsNone; public class SourceDefinition8 { @JsonProperty("driverId") public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = CustomGenerator.class, property = "name") @JsonProperty("CustomGenerator") public SourceDefinition9 testCustomGenerator; public class SourceDefinition9 { public String driver; public String name; } @JsonIdentityInfo(generator = CustomGenerator.class, property = "name") @JsonProperty("WithoutJsonIdentityReference") public SourceDefinition10 testWithoutJsonIdentityReference; public class SourceDefinition10 { public String driver; public String name; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/ModelWithJsonIdentityCyclic.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import java.util.List; public class ModelWithJsonIdentityCyclic { public Long id; public List sourceDefinitions; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") public static class SourceDefinition { public String driver; public String name; @JsonIdentityReference(alwaysAsId=true) @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public ModelWithJsonIdentityCyclic model; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/MultipleBaseBean.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleBaseBean", subTypes = { MultipleSub1Bean.class, MultipleSub2Bean.class } ) public class MultipleBaseBean { public String beanType; public int a; public String b; } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/MultipleSub1Bean.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleSub1Bean" ) public class MultipleSub1Bean extends MultipleBaseBean { public int c; } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/MultipleSub2Bean.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleSub2Bean" ) public class MultipleSub2Bean extends MultipleBaseBean { public int d; } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/NotFoundModel.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; public class NotFoundModel { int code; String message; public NotFoundModel() { } public NotFoundModel(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/Pet.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.util.ArrayList; import java.util.List; @XmlRootElement(name = "Pet") public class Pet { private long id; private Category category; private String name; private List photoUrls = new ArrayList(); private List tags = new ArrayList(); private String status; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "category") public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElementWrapper(name = "photoUrls") @XmlElement(name = "photoUrl") public List getPhotoUrls() { return photoUrls; } public void setPhotoUrls(List photoUrls) { this.photoUrls = photoUrls; } @XmlElementWrapper(name = "tags") @XmlElement(name = "tag") public List getTags() { return tags; } public void setTags(List tags) { this.tags = tags; } @XmlElement(name = "status") @Schema(description = "pet status in the store", allowableValues = "available,pending,sold") public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/Tag.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Tag") public class Tag { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: modules/swagger-gradle-plugin/src/test/java/io/swagger/v3/plugins/gradle/resources/model/User.java ================================================ package io.swagger.v3.plugins.gradle.resources.model; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "User") public class User { private long id; private String username; private String firstName; private String lastName; private String email; private String password; private String phone; private int userStatus; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "firstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement(name = "lastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone") public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @XmlElement(name = "userStatus") //@Schema(description = "User Status", type = "string", allowableValues = {"1-registered", "2-active", "3-closed"}) @Schema(description = "User Status", allowableValues = "1-registered,2-active,3-closed") public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } } ================================================ FILE: modules/swagger-integration/pom.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-project 2.2.46-SNAPSHOT ../.. swagger-integration swagger-integration swagger-integration io.github.classgraph classgraph jakarta.ws.rs jakarta.ws.rs-api test org.testng testng test io.swagger.core.v3 swagger-core ${project.version} io.swagger.core.v3 swagger-models ${project.version} src/main/java install biz.aQute.bnd bnd-maven-plugin org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF io.swagger.v3.oas.integration ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/ClasspathOpenApiConfigurationLoader.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import java.io.IOException; public class ClasspathOpenApiConfigurationLoader implements StringOpenApiConfigurationLoader { @Override public OpenAPIConfiguration load(String path) throws IOException { String sanitized = (path.startsWith("/") ? path : "/" + path); String configString = readInputStreamToString(this.getClass().getResource(sanitized).openStream()); return deserializeConfig(path, configString); } @Override public boolean exists(String path) { String sanitized = (path.startsWith("/") ? path : "/" + path); return this.getClass().getResource(sanitized) != null; } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/ContextUtils.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ContextUtils { private static Logger LOGGER = LoggerFactory.getLogger(ContextUtils.class); // TODO implement proper clone see #2227 public static OpenAPIConfiguration deepCopy(OpenAPIConfiguration config) { if (config == null) { return null; } try { return Json.mapper().readValue(Json.pretty(config), SwaggerConfiguration.class); } catch (Exception e) { LOGGER.error("Exception cloning config: " + e.getMessage(), e); return config; } } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/FileOpenApiConfigurationLoader.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class FileOpenApiConfigurationLoader implements StringOpenApiConfigurationLoader { @Override public OpenAPIConfiguration load(String path) throws IOException { File file = new File(path); return deserializeConfig(path, readInputStreamToString(new FileInputStream(file))); } @Override public boolean exists(String path) { File file = new File(path); return file.exists(); } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContext.java ================================================ package io.swagger.v3.oas.integration; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.filter.OpenAPI31SpecFilter; import io.swagger.v3.core.filter.SpecFilter; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.jackson.PathsSerializer; import io.swagger.v3.core.jackson.mixin.Schema31Mixin; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.integration.api.ObjectMapperProcessor; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiConfigurationLoader; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.integration.api.OpenApiReader; import io.swagger.v3.oas.integration.api.OpenApiScanner; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.math.BigDecimal; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class GenericOpenApiContext implements OpenApiContext { private static Logger LOGGER = LoggerFactory.getLogger(GenericOpenApiContext.class); protected Set resourcePackages; protected Set resourceClasses; protected String id = OPENAPI_CONTEXT_ID_DEFAULT; protected OpenApiContext parent; protected String configLocation; private OpenAPIConfiguration openApiConfiguration; private OpenApiReader openApiReader; private OpenApiScanner openApiScanner; private OpenApiReader providedOpenApiReader; private ObjectMapperProcessor objectMapperProcessor; private Set modelConverters; private ObjectMapper outputJsonMapper; private ObjectMapper outputYamlMapper; private ConcurrentHashMap cache = new ConcurrentHashMap<>(); // 0 doesn't cache // -1 perpetual private long cacheTTL = -1; private Boolean openAPI31; private Boolean convertToOpenAPI31; private Schema.SchemaResolution schemaResolution; private String openAPIVersion; public long getCacheTTL() { return cacheTTL; } public void setCacheTTL(long cacheTTL) { this.cacheTTL = cacheTTL; } public T cacheTTL(long cacheTTL) { this.cacheTTL = cacheTTL; return (T) this; } public OpenApiReader getOpenApiReader() { return openApiReader; } @Override public void setOpenApiReader(OpenApiReader openApiReader) { this.openApiReader = openApiReader; providedOpenApiReader = openApiReader; } public OpenApiScanner getOpenApiScanner() { return openApiScanner; } @Override public void setOpenApiScanner(OpenApiScanner openApiScanner) { this.openApiScanner = openApiScanner; } public final T openApiReader(OpenApiReader openApiReader) { setOpenApiReader(openApiReader); return (T) this; } public final T openApiScanner(OpenApiScanner openApiScanner) { this.openApiScanner = openApiScanner; return (T) this; } public Set getResourcePackages() { return resourcePackages; } public void setResourcePackages(Set resourcePackages) { this.resourcePackages = resourcePackages; } public T resourcePackages(Set resourcePackages) { this.resourcePackages = resourcePackages; return (T) this; } public Set getResourceClasses() { return resourceClasses; } public void setResourceClasses(Set resourceClasses) { this.resourceClasses = resourceClasses; } public T resourceClasses(Set resourceClasses) { this.resourceClasses = resourceClasses; return (T) this; } public T openApiConfiguration(OpenAPIConfiguration openApiConfiguration) { this.openApiConfiguration = openApiConfiguration; return (T) this; } @Override public String getConfigLocation() { return configLocation; } public void setConfigLocation(String configLocation) { this.configLocation = configLocation; } public final T configLocation(String configLocation) { this.configLocation = configLocation; return (T) this; } @Override public String getId() { return this.id; } public void setId(String id) { this.id = id; } public final T id(String id) { this.id = id; return (T) this; } @Override public OpenApiContext getParent() { return this.parent; } public void setParent(OpenApiContext parent) { this.parent = parent; } public final T parent(OpenApiContext parent) { this.parent = parent; return (T) this; } /** * @since 2.0.6 */ public ObjectMapperProcessor getObjectMapperProcessor() { return objectMapperProcessor; } /** * @since 2.0.6 */ @Override public void setObjectMapperProcessor(ObjectMapperProcessor objectMapperProcessor) { this.objectMapperProcessor = objectMapperProcessor; } /** * @since 2.0.6 */ public final T objectMapperProcessor(ObjectMapperProcessor objectMapperProcessor) { this.objectMapperProcessor = objectMapperProcessor; return (T) this; } /** * @since 2.0.6 */ public Set getModelConverters() { return modelConverters; } /** * @since 2.0.6 */ @Override public void setModelConverters(Set modelConverters) { this.modelConverters = modelConverters; } /** * @since 2.0.6 */ public final T modelConverters(Set modelConverters) { this.modelConverters = modelConverters; return (T) this; } /** * @since 2.1.6 */ public ObjectMapper getOutputJsonMapper() { return outputJsonMapper; } /** * @since 2.1.6 */ @Override public void setOutputJsonMapper(ObjectMapper outputJsonMapper) { this.outputJsonMapper = outputJsonMapper; } /** * @since 2.1.6 */ public final T outputJsonMapper(ObjectMapper outputJsonMapper) { this.outputJsonMapper = outputJsonMapper; return (T) this; } /** * @since 2.1.6 */ public ObjectMapper getOutputYamlMapper() { return outputYamlMapper; } /** * @since 2.1.6 */ @Override public void setOutputYamlMapper(ObjectMapper outputYamlMapper) { this.outputYamlMapper = outputYamlMapper; } /** * @since 2.1.6 */ public final T outputYamlMapper(ObjectMapper outputYamlMapper) { this.outputYamlMapper = outputYamlMapper; return (T) this; } /** * @since 2.1.8 */ public Boolean isOpenAPI31() { return openAPI31; } /** * @since 2.1.8 */ public void setOpenAPI31(Boolean v) { this.openAPI31 = openAPI31; } /** * @since 2.1.8 */ public T openAPI31(Boolean openAPI31) { this.openAPI31 = openAPI31; return (T) this; } /** * @since 2.2.12 */ public Boolean isConvertToOpenAPI31() { return convertToOpenAPI31; } /** * @since 2.2.12 */ public void setConvertToOpenAPI31(Boolean convertToOpenAPI31) { this.convertToOpenAPI31 = convertToOpenAPI31; if (Boolean.TRUE.equals(convertToOpenAPI31)) { this.openAPI31 = true; } } /** * @since 2.2.12 */ public T convertToOpenAPI31(Boolean convertToOpenAPI31) { this.setConvertToOpenAPI31(convertToOpenAPI31); return (T) this; } /** * @since 2.2.24 */ public Schema.SchemaResolution getSchemaResolution() { return schemaResolution; } /** * @since 2.2.24 */ public void setSchemaResolution(Schema.SchemaResolution schemaResolution) { this.schemaResolution = schemaResolution; } /** * @since 2.2.24 */ public T schemaResolution(Schema.SchemaResolution schemaResolution) { this.schemaResolution = schemaResolution; return (T) this; } /** * @since 2.2.28 */ public String getOpenAPIVersion() { return openAPIVersion; } /** * @since 2.2.28 */ public void setOpenAPIVersion(String openAPIVersion) { this.openAPIVersion = openAPIVersion; } /** * @since 2.2.28 */ public T openAPIVersion(String openAPIVersion) { this.openAPIVersion = openAPIVersion; return (T) this; } protected void register() { OpenApiContextLocator.getInstance().putOpenApiContext(id, this); } @Override public OpenAPIConfiguration getOpenApiConfiguration() { return openApiConfiguration; } public void setOpenApiConfiguration(OpenAPIConfiguration openApiConfiguration) { this.openApiConfiguration = openApiConfiguration; } protected OpenApiReader buildReader(final OpenAPIConfiguration openApiConfiguration) throws Exception { OpenApiReader reader; if (StringUtils.isNotBlank(openApiConfiguration.getReaderClass())) { Class cls = getClass().getClassLoader().loadClass(openApiConfiguration.getReaderClass()); reader = (OpenApiReader) cls.newInstance(); } else { reader = new OpenApiReader() { OpenAPIConfiguration openApiConfiguration; @Override public void setConfiguration(OpenAPIConfiguration openApiConfiguration) { this.openApiConfiguration = openApiConfiguration; } @Override public OpenAPI read(Set> classes, Map resources) { return openApiConfiguration.getOpenAPI(); } }; } reader.setConfiguration(openApiConfiguration); return reader; } protected OpenApiScanner buildScanner(final OpenAPIConfiguration openApiConfiguration) throws Exception { OpenApiScanner scanner; if (StringUtils.isNotBlank(openApiConfiguration.getScannerClass())) { Class cls = getClass().getClassLoader().loadClass(openApiConfiguration.getScannerClass()); scanner = (OpenApiScanner) cls.newInstance(); } else { scanner = new GenericOpenApiScanner(); } scanner.setConfiguration(openApiConfiguration); return scanner; } protected ObjectMapperProcessor buildObjectMapperProcessor(final OpenAPIConfiguration openApiConfiguration) throws Exception { ObjectMapperProcessor objectMapperProcessor = null; if (StringUtils.isNotBlank(openApiConfiguration.getObjectMapperProcessorClass())) { Class cls = getClass().getClassLoader().loadClass(openApiConfiguration.getObjectMapperProcessorClass()); objectMapperProcessor = (ObjectMapperProcessor) cls.newInstance(); } return objectMapperProcessor; } protected Set buildModelConverters(final OpenAPIConfiguration openApiConfiguration) throws Exception { if (openApiConfiguration.getModelConverterClasses() != null && !openApiConfiguration.getModelConverterClasses().isEmpty()) { LinkedHashSet modelConverters = new LinkedHashSet<>(); for (String converterClass: openApiConfiguration.getModelConverterClasses()) { Class cls = getClass().getClassLoader().loadClass(converterClass); ModelConverter converter = (ModelConverter) cls.newInstance(); modelConverters.add(converter); } return modelConverters; } return null; } protected List> getKnownLocations() { return Arrays.asList( new ImmutablePair<>("classpath", "openapi-configuration.yaml"), new ImmutablePair<>("classpath", "openapi-configuration.json"), new ImmutablePair<>("file", "openapi-configuration.yaml"), new ImmutablePair<>("file", "openapi-configuration.json"), new ImmutablePair<>("classpath", "openapi.yaml"), new ImmutablePair<>("classpath", "openapi.json"), new ImmutablePair<>("file", "openapi.yaml"), new ImmutablePair<>("file", "openapi.json"), new ImmutablePair<>("service", "") ); } protected Map getLocationLoaders() { Map map = new HashMap<>(); map.put("classpath", new ClasspathOpenApiConfigurationLoader()); map.put("file", new FileOpenApiConfigurationLoader()); map.put("url", new URLOpenApiConfigurationLoader()); map.put("service", new ServiceOpenApiConfigurationLoader()); return map; } protected OpenAPIConfiguration loadConfiguration() throws OpenApiConfigurationException { Map loaders = getLocationLoaders(); try { if (StringUtils.isNotEmpty(configLocation)) { if (loaders.get("classpath").exists(configLocation)) { return loaders.get("classpath").load(configLocation); } if (loaders.get("file").exists(configLocation)) { return loaders.get("file").load(configLocation); } } // check known locations List> knownLocations = getKnownLocations(); for (ImmutablePair location : knownLocations) { if (loaders.get(location.left).exists(location.right)) { try { return loaders.get(location.left).load(location.right); } catch (IOException ioe) { // try next one } } } return null; } catch (Exception e) { throw new OpenApiConfigurationException(e.getMessage(), e); } } @Override public T init() throws OpenApiConfigurationException { if (openApiConfiguration == null) { openApiConfiguration = loadConfiguration(); } if (openApiConfiguration == null) { openApiConfiguration = new SwaggerConfiguration().resourcePackages(resourcePackages).resourceClasses(resourceClasses); ((SwaggerConfiguration) openApiConfiguration).setId(id); ((SwaggerConfiguration) openApiConfiguration).setOpenAPI31(openAPI31); ((SwaggerConfiguration) openApiConfiguration).setConvertToOpenAPI31(convertToOpenAPI31); if (schemaResolution != null) { ((SwaggerConfiguration) openApiConfiguration).setSchemaResolution(schemaResolution); } if (openAPIVersion != null && !openAPIVersion.isEmpty()) { ((SwaggerConfiguration) openApiConfiguration).openAPIVersion(openAPIVersion); ((SwaggerConfiguration) openApiConfiguration).setSchemaResolution(schemaResolution); } } openApiConfiguration = mergeParentConfiguration(openApiConfiguration, parent); try { if (openApiReader == null) { openApiReader = buildReader(ContextUtils.deepCopy(openApiConfiguration)); } if (openApiScanner == null) { openApiScanner = buildScanner(ContextUtils.deepCopy(openApiConfiguration)); } if (objectMapperProcessor == null) { objectMapperProcessor = buildObjectMapperProcessor(ContextUtils.deepCopy(openApiConfiguration)); } if (modelConverters == null || modelConverters.isEmpty()) { modelConverters = buildModelConverters(ContextUtils.deepCopy(openApiConfiguration)); } if (outputJsonMapper == null) { if (Boolean.TRUE.equals(openApiConfiguration.isOpenAPI31())) { outputJsonMapper = Json31.mapper().copy(); } else { outputJsonMapper = Json.mapper().copy(); } } if (outputYamlMapper == null) { if (Boolean.TRUE.equals(openApiConfiguration.isOpenAPI31())) { outputYamlMapper = Yaml31.mapper().copy(); } else { outputYamlMapper = Yaml.mapper().copy(); } } if (openApiConfiguration.isSortOutput() != null && openApiConfiguration.isSortOutput()) { outputJsonMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); outputJsonMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); outputYamlMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); outputYamlMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); if (Boolean.TRUE.equals(openApiConfiguration.isOpenAPI31())) { outputJsonMapper.addMixIn(OpenAPI.class, SortedOpenAPIMixin31.class); outputJsonMapper.addMixIn(Schema.class, SortedSchemaMixin31.class); outputYamlMapper.addMixIn(OpenAPI.class, SortedOpenAPIMixin31.class); outputYamlMapper.addMixIn(Schema.class, SortedSchemaMixin31.class); } else { outputJsonMapper.addMixIn(OpenAPI.class, SortedOpenAPIMixin.class); outputJsonMapper.addMixIn(Schema.class, SortedSchemaMixin.class); outputYamlMapper.addMixIn(OpenAPI.class, SortedOpenAPIMixin.class); outputYamlMapper.addMixIn(Schema.class, SortedSchemaMixin.class); } } } catch (Exception e) { LOGGER.error("error initializing context: " + e.getMessage(), e); throw new OpenApiConfigurationException("error initializing context: " + e.getMessage(), e); } try { if (objectMapperProcessor != null) { ObjectMapper mapper = IntegrationObjectMapperFactory.createJson(); objectMapperProcessor.processJsonObjectMapper(mapper); ModelConverters.getInstance(Boolean.TRUE.equals(openApiConfiguration.isOpenAPI31()), openApiConfiguration.getSchemaResolution()).addConverter(new ModelResolver(mapper)); objectMapperProcessor.processOutputJsonObjectMapper(outputJsonMapper); objectMapperProcessor.processOutputYamlObjectMapper(outputYamlMapper); } } catch (Exception e) { LOGGER.error("error configuring objectMapper: " + e.getMessage(), e); throw new OpenApiConfigurationException("error configuring objectMapper: " + e.getMessage(), e); } try { if (modelConverters != null && !modelConverters.isEmpty()) { for (ModelConverter converter: modelConverters) { ModelConverters.getInstance(Boolean.TRUE.equals(openApiConfiguration.isOpenAPI31())).addConverter(converter); } } } catch (Exception e) { LOGGER.error("error configuring model converters: " + e.getMessage(), e); throw new OpenApiConfigurationException("error configuring model converters: " + e.getMessage(), e); } // set cache TTL if present in configuration if (openApiConfiguration.getCacheTTL() != null) { this.cacheTTL = openApiConfiguration.getCacheTTL(); } // set openAPI31 if present in configuration if (openApiConfiguration.isOpenAPI31() != null && this.openAPI31 == null) { this.openAPI31 = openApiConfiguration.isOpenAPI31(); } if (openApiConfiguration.isConvertToOpenAPI31() != null && this.convertToOpenAPI31 == null) { this.convertToOpenAPI31 = openApiConfiguration.isConvertToOpenAPI31(); } if (openApiConfiguration.getSchemaResolution() != null && this.getSchemaResolution() == null) { this.schemaResolution = openApiConfiguration.getSchemaResolution(); } register(); return (T) this; } private OpenAPIConfiguration mergeParentConfiguration(OpenAPIConfiguration config, OpenApiContext parent) { if (parent == null || parent.getOpenApiConfiguration() == null) { return config; } OpenAPIConfiguration parentConfig = parent.getOpenApiConfiguration(); SwaggerConfiguration merged = null; if (config instanceof SwaggerConfiguration) { merged = (SwaggerConfiguration) config; } else { merged = (SwaggerConfiguration) ContextUtils.deepCopy(config); } if (merged.getResourceClasses() == null) { merged.setResourceClasses(parentConfig.getResourceClasses()); } if (merged.getFilterClass() == null) { merged.setFilterClass(parentConfig.getFilterClass()); } if (merged.getIgnoredRoutes() == null) { merged.setIgnoredRoutes(parentConfig.getIgnoredRoutes()); } if (merged.getOpenAPI() == null) { merged.setOpenAPI(parentConfig.getOpenAPI()); } if (merged.getReaderClass() == null) { merged.setReaderClass(parentConfig.getReaderClass()); } if (merged.getResourcePackages() == null) { merged.setResourcePackages(parentConfig.getResourcePackages()); } if (merged.getScannerClass() == null) { merged.setScannerClass(parentConfig.getScannerClass()); } if (merged.getCacheTTL() == null) { merged.setCacheTTL(parentConfig.getCacheTTL()); } if (merged.getUserDefinedOptions() == null) { merged.setUserDefinedOptions(parentConfig.getUserDefinedOptions()); } if (merged.isPrettyPrint() == null) { merged.setPrettyPrint(parentConfig.isPrettyPrint()); } if (merged.isSortOutput() == null) { merged.setSortOutput(parentConfig.isSortOutput()); } if (merged.isAlwaysResolveAppPath() == null) { merged.setAlwaysResolveAppPath(parentConfig.isAlwaysResolveAppPath()); } if (merged.isSkipResolveAppPath() == null) { merged.setSkipResolveAppPath(parentConfig.isSkipResolveAppPath()); } if (merged.isReadAllResources() == null) { merged.setReadAllResources(parentConfig.isReadAllResources()); } if (merged.getObjectMapperProcessorClass() == null) { merged.setObjectMapperProcessorClass(parentConfig.getObjectMapperProcessorClass()); } if (merged.getModelConverterClasses() == null) { merged.setModelConverterClassess(parentConfig.getModelConverterClasses()); } if (merged.isOpenAPI31() == null) { merged.setOpenAPI31(parentConfig.isOpenAPI31()); } if (merged.isConvertToOpenAPI31() == null) { merged.setConvertToOpenAPI31(parentConfig.isConvertToOpenAPI31()); } if (merged.getDefaultResponseCode() == null) { merged.setDefaultResponseCode(parentConfig.getDefaultResponseCode()); } if (merged.getSchemaResolution() == null) { merged.setSchemaResolution(parentConfig.getSchemaResolution()); } if (merged.getValidatorProcessorClass() == null) { merged.setValidatorProcessorClass(parentConfig.getValidatorProcessorClass()); } if (merged.getGroupsValidationStrategy() == null || merged.getGroupsValidationStrategy().equals(Configuration.GroupsValidationStrategy.DEFAULT)) { merged.setGroupsValidationStrategy(parentConfig.getGroupsValidationStrategy()); } return merged; } @Override public OpenAPI read() { if (cacheTTL == 0) { resetReader(); OpenAPI openAPI = getOpenApiReader().read(getOpenApiScanner().classes(), getOpenApiScanner().resources()); if (Boolean.TRUE.equals(convertToOpenAPI31)) { openAPI = new SpecFilter().filter(openAPI, new OpenAPI31SpecFilter(), null, null, null); } return openAPI; } Cache cached = cache.get("openapi"); if (cached == null || cached.isStale(cacheTTL)) { cached = new Cache(); cached.createdAt = System.currentTimeMillis(); resetReader(); cached.openApi = getOpenApiReader().read(getOpenApiScanner().classes(), getOpenApiScanner().resources()); if (Boolean.TRUE.equals(convertToOpenAPI31)) { cached.openApi = new SpecFilter().filter(cached.openApi, new OpenAPI31SpecFilter(), null, null, null); } cache.put("openapi", cached); } return cached.openApi; } protected void resetReader() { if (providedOpenApiReader == null) { try { openApiReader = buildReader(ContextUtils.deepCopy(openApiConfiguration)); } catch (Exception e) { LOGGER.error("error building reader: " + e.getMessage(), e); // keep previous reader } } } static class Cache { long createdAt = 0; OpenAPI openApi; boolean isStale(long cacheTTL) { return (cacheTTL > 0 && System.currentTimeMillis() - createdAt > cacheTTL); } } @JsonPropertyOrder(value = {"openapi", "info", "externalDocs", "servers", "security", "tags", "paths", "components"}, alphabetic = true) static abstract class SortedOpenAPIMixin { @JsonAnyGetter @JsonPropertyOrder(alphabetic = true) public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonSerialize(using = PathsSerializer.class) public abstract Paths getPaths(); } @JsonPropertyOrder(value = {"type", "format"}, alphabetic = true) static abstract class SortedSchemaMixin { @JsonAnyGetter @JsonPropertyOrder(alphabetic = true) public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonIgnore public abstract boolean getExampleSetFlag(); @JsonInclude(value = JsonInclude.Include.NON_NULL, content = JsonInclude.Include.ALWAYS) public abstract Object getExample(); @JsonIgnore public abstract Map getJsonSchema(); @JsonIgnore public abstract BigDecimal getExclusiveMinimumValue(); @JsonIgnore public abstract BigDecimal getExclusiveMaximumValue(); @JsonIgnore public abstract Map getPatternProperties(); @JsonIgnore public abstract Schema getContains(); @JsonIgnore public abstract String get$id(); @JsonIgnore public abstract String get$anchor(); @JsonIgnore public abstract String get$schema(); @JsonIgnore public abstract Set getTypes(); @JsonIgnore public abstract Object getJsonSchemaImpl(); @JsonIgnore public abstract List getPrefixItems(); @JsonIgnore public abstract String getContentEncoding(); @JsonIgnore public abstract String getContentMediaType(); @JsonIgnore public abstract Schema getContentSchema(); @JsonIgnore public abstract Schema getPropertyNames(); @JsonIgnore public abstract Object getUnevaluatedProperties(); @JsonIgnore public abstract Integer getMaxContains(); @JsonIgnore public abstract Integer getMinContains(); @JsonIgnore public abstract Schema getAdditionalItems(); @JsonIgnore public abstract Schema getUnevaluatedItems(); @JsonIgnore public abstract Schema getIf(); @JsonIgnore public abstract Schema getElse(); @JsonIgnore public abstract Schema getThen(); @JsonIgnore public abstract Map getDependentSchemas(); @JsonIgnore public abstract Map> getDependentRequired(); @JsonIgnore public abstract String get$comment(); @JsonIgnore public abstract List getExamples(); @JsonIgnore public abstract Object getConst(); @JsonIgnore public abstract Boolean getBooleanSchemaValue(); } @JsonPropertyOrder(value = {"openapi", "info", "externalDocs", "servers", "security", "tags", "paths", "components", "webhooks"}, alphabetic = true) static abstract class SortedOpenAPIMixin31 { @JsonAnyGetter @JsonPropertyOrder(alphabetic = true) public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonSerialize(using = PathsSerializer.class) public abstract Paths getPaths(); } @JsonPropertyOrder(value = {"type", "format", "if", "then", "else"}, alphabetic = true) static abstract class SortedSchemaMixin31 { @JsonAnyGetter @JsonPropertyOrder(alphabetic = true) public abstract Map getExtensions(); @JsonIgnore public abstract Map getJsonSchema(); @JsonIgnore public abstract Boolean getNullable(); @JsonIgnore public abstract Boolean getExclusiveMinimum(); @JsonIgnore public abstract Boolean getExclusiveMaximum(); @JsonProperty("exclusiveMinimum") public abstract BigDecimal getExclusiveMinimumValue(); @JsonProperty("exclusiveMaximum") public abstract BigDecimal getExclusiveMaximumValue(); @JsonIgnore public abstract String getType(); @JsonProperty("type") @JsonSerialize(using = Schema31Mixin.TypeSerializer.class) public abstract Set getTypes(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonIgnore public abstract boolean getExampleSetFlag(); @JsonInclude(value = JsonInclude.Include.NON_NULL, content = JsonInclude.Include.ALWAYS) public abstract Object getExample(); @JsonIgnore public abstract Object getJsonSchemaImpl(); @JsonIgnore public abstract Boolean getBooleanSchemaValue(); } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiContextBuilder.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.integration.api.OpenApiContextBuilder; import org.apache.commons.lang3.StringUtils; import java.util.Set; public class GenericOpenApiContextBuilder implements OpenApiContextBuilder { protected String ctxId; protected String configLocation; protected Set resourcePackages; protected Set resourceClasses; protected OpenAPIConfiguration openApiConfiguration; @Override public OpenApiContext buildContext(boolean init) throws OpenApiConfigurationException { if (StringUtils.isBlank(ctxId)) { ctxId = OpenApiContext.OPENAPI_CONTEXT_ID_DEFAULT; } OpenApiContext ctx = OpenApiContextLocator.getInstance().getOpenApiContext(ctxId); if (ctx == null) { OpenApiContext rootCtx = OpenApiContextLocator.getInstance().getOpenApiContext(OpenApiContext.OPENAPI_CONTEXT_ID_DEFAULT); ctx = new GenericOpenApiContext() .openApiConfiguration(openApiConfiguration) .id(ctxId) .parent(rootCtx); if (ctx.getConfigLocation() == null && configLocation != null) { ((GenericOpenApiContext) ctx).configLocation(configLocation); } if (((GenericOpenApiContext) ctx).getResourcePackages() == null && resourcePackages != null) { ((GenericOpenApiContext) ctx).resourcePackages(resourcePackages); } if (((GenericOpenApiContext) ctx).getResourceClasses() == null && resourceClasses != null) { ((GenericOpenApiContext) ctx).resourceClasses(resourceClasses); } if (init) { ctx.init(); // includes registering itself with OpenApiContextLocator } } return ctx; } public String getCtxId() { return ctxId; } public void setCtxId(String ctxId) { this.ctxId = ctxId; } public String getConfigLocation() { return configLocation; } public void setConfigLocation(String configLocation) { this.configLocation = configLocation; } public Set getResourcePackages() { return resourcePackages; } public void setResourcePackages(Set resourcePackages) { this.resourcePackages = resourcePackages; } public OpenAPIConfiguration getOpenApiConfiguration() { return openApiConfiguration; } public void setOpenApiConfiguration(OpenAPIConfiguration openApiConfiguration) { this.openApiConfiguration = openApiConfiguration; } public T ctxId(String ctxId) { this.ctxId = ctxId; return (T) this; } public T configLocation(String configLocation) { this.configLocation = configLocation; return (T) this; } public T resourcePackages(Set resourcePackages) { this.resourcePackages = resourcePackages; return (T) this; } public T openApiConfiguration(OpenAPIConfiguration openApiConfiguration) { this.openApiConfiguration = openApiConfiguration; return (T) this; } public Set getResourceClasses() { return resourceClasses; } public void setResourceClasses(Set resourceClasses) { this.resourceClasses = resourceClasses; } public T resourceClasses(Set resourceClasses) { this.resourceClasses = resourceClasses; return (T) this; } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/GenericOpenApiScanner.java ================================================ package io.swagger.v3.oas.integration; import io.github.classgraph.ClassGraph; import io.github.classgraph.ScanResult; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Webhooks; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiScanner; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public class GenericOpenApiScanner implements OpenApiScanner { static final Set ignored = new HashSet<>(); static { ignored.addAll(IgnoredPackages.ignored); } private static Logger LOGGER = LoggerFactory.getLogger(GenericOpenApiScanner.class); OpenAPIConfiguration openApiConfiguration; @Override public void setConfiguration(OpenAPIConfiguration openApiConfiguration) { this.openApiConfiguration = openApiConfiguration; } @Override public Set> classes() { ClassGraph graph = new ClassGraph().enableAllInfo(); Set acceptablePackages = new HashSet<>(); Set> output = new HashSet<>(); boolean allowAllPackages = false; // if classes are passed, use them if (openApiConfiguration.getResourceClasses() != null && !openApiConfiguration.getResourceClasses().isEmpty()) { for (String className : openApiConfiguration.getResourceClasses()) { if (!isIgnored(className)) { try { output.add(Class.forName(className)); } catch (ClassNotFoundException e) { LOGGER.warn("error loading class from resourceClasses: " + e.getMessage(), e); } } } return output; } if (openApiConfiguration.getResourcePackages() != null && !openApiConfiguration.getResourcePackages().isEmpty()) { for (String pkg : openApiConfiguration.getResourcePackages()) { if (!isIgnored(pkg)) { acceptablePackages.add(pkg); graph.whitelistPackages(pkg); } } } else { allowAllPackages = true; } // this is generic, specific Jaxrs scanner will also look for @Path final Set> classes; try (ScanResult scanResult = graph.scan()) { classes = new HashSet<>(scanResult.getClassesWithAnnotation(OpenAPIDefinition.class.getName()).loadClasses()); classes.addAll(new HashSet<>(scanResult.getClassesWithAnnotation(Webhooks.class.getName()).loadClasses())); } for (Class cls : classes) { if (allowAllPackages) { output.add(cls); } else { for (String pkg : acceptablePackages) { if (cls.getPackage().getName().startsWith(pkg)) { output.add(cls); } } } } return output; } @Override public Map resources() { return new HashMap<>(); } protected boolean isIgnored(String classOrPackageName) { if (StringUtils.isBlank(classOrPackageName)) { return true; } return ignored.stream().anyMatch(classOrPackageName::startsWith); } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/IgnoredPackages.java ================================================ package io.swagger.v3.oas.integration; import java.util.HashSet; import java.util.Set; public final class IgnoredPackages { public static final Set ignored = new HashSet<>(); static { ignored.add("io.swagger.v3.jaxrs2.integration.resources"); ignored.add("org.glassfish.jersey"); ignored.add("org.jboss.resteasy"); ignored.add("com.sun.jersey"); ignored.add("com.fasterxml.jackson"); } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/IntegrationObjectMapperFactory.java ================================================ package io.swagger.v3.oas.integration; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.util.ObjectMapperFactory; public class IntegrationObjectMapperFactory extends ObjectMapperFactory { public static ObjectMapper createJson() { return ObjectMapperFactory.createJson(); } public static ObjectMapper createJson31() { return ObjectMapperFactory.createJson31(); } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/OpenApiConfigurationException.java ================================================ package io.swagger.v3.oas.integration; public class OpenApiConfigurationException extends Exception { public OpenApiConfigurationException(String message, Throwable cause) { super(message, cause); } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/OpenApiContextLocator.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.oas.integration.api.OpenApiContext; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class OpenApiContextLocator { private static OpenApiContextLocator instance; private ConcurrentMap map = new ConcurrentHashMap<>(); private OpenApiContextLocator() { } public static synchronized OpenApiContextLocator getInstance() { if (instance == null) { instance = new OpenApiContextLocator(); } return instance; } public OpenApiContext getOpenApiContext(String id) { return map.get(id); } public void putOpenApiContext(String id, OpenApiContext openApiContext) { map.put(id, openApiContext); } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/ServiceOpenApiConfigurationLoader.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.oas.integration.api.OpenAPIConfigBuilder; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiConfigurationLoader; import java.io.IOException; import java.util.ServiceLoader; // doesn't support multiple configs public class ServiceOpenApiConfigurationLoader implements OpenApiConfigurationLoader { @Override public OpenAPIConfiguration load(String path) throws IOException { ServiceLoader loader = ServiceLoader.load(OpenAPIConfigBuilder.class); if (loader.iterator().hasNext()) { return loader.iterator().next().build(); } throw new IOException("Error loading OpenAPIConfigBuilder service implementation."); } @Override public boolean exists(String path) { try { ServiceLoader loader = ServiceLoader.load(OpenAPIConfigBuilder.class); if (loader.iterator().hasNext()) { loader.iterator().next(); return true; } return false; } catch (Exception e) { return false; } } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/StringOpenApiConfigurationLoader.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiConfigurationLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public interface StringOpenApiConfigurationLoader extends OpenApiConfigurationLoader { Logger LOGGER = LoggerFactory.getLogger(StringOpenApiConfigurationLoader.class); default OpenAPIConfiguration deserializeConfig(String path, String configAsString) { try { if (path.toLowerCase().endsWith("json")) { return Json.mapper().readValue(configAsString, SwaggerConfiguration.class); } else { // assume yaml return Yaml.mapper().readValue(configAsString, SwaggerConfiguration.class); } } catch (Exception e) { LOGGER.error("exception reading config: " + e.getMessage(), e); return null; } } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/SwaggerConfiguration.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import java.util.Collection; import java.util.Map; import java.util.Set; public class SwaggerConfiguration implements OpenAPIConfiguration { Map userDefinedOptions; private OpenAPI openAPI; private String id; private Set resourcePackages; private Set resourceClasses; private String filterClass; private String readerClass; private String scannerClass; private Boolean prettyPrint; // read all operations also with no @Operation; set to false to read only methods annotated with @Operation private Boolean readAllResources = Boolean.TRUE; private Collection ignoredRoutes; private Long cacheTTL = -1L; private Set modelConverterClasses; private String objectMapperProcessorClass; private Boolean sortOutput; private Boolean alwaysResolveAppPath; private Boolean skipResolveAppPath; private Boolean openAPI31 = false; private Boolean convertToOpenAPI31; private Schema.SchemaResolution schemaResolution = Schema.SchemaResolution.DEFAULT; private String openAPIVersion; private Configuration.GroupsValidationStrategy groupsValidationStrategy = Configuration.GroupsValidationStrategy.DEFAULT; private String validatorProcessorClass; @Override public String getDefaultResponseCode() { return defaultResponseCode; } public void setDefaultResponseCode(String defaultResponseCode) { this.defaultResponseCode = defaultResponseCode; } public SwaggerConfiguration defaultResponseCode(String defaultResponseCode) { this.defaultResponseCode = defaultResponseCode; return this; } private String defaultResponseCode; public Long getCacheTTL() { return cacheTTL; } public void setCacheTTL(Long cacheTTL) { this.cacheTTL = cacheTTL; } public SwaggerConfiguration cacheTTL(Long cacheTTL) { this.cacheTTL = cacheTTL; return this; } public Boolean isReadAllResources() { return readAllResources; } public void setReadAllResources(Boolean readAllResources) { this.readAllResources = readAllResources; } public SwaggerConfiguration readAllResources(Boolean readAllResources) { this.readAllResources = readAllResources; return this; } public Collection getIgnoredRoutes() { return ignoredRoutes; } public void setIgnoredRoutes(Collection ignoredRoutes) { this.ignoredRoutes = ignoredRoutes; } public SwaggerConfiguration ignoredRoutes(Collection ignoredRoutes) { this.ignoredRoutes = ignoredRoutes; return this; } public Boolean isPrettyPrint() { return prettyPrint; } public void setPrettyPrint(Boolean prettyPrint) { this.prettyPrint = prettyPrint; } public SwaggerConfiguration prettyPrint(Boolean prettyPrint) { this.prettyPrint = prettyPrint; return this; } @Override public OpenAPI getOpenAPI() { return openAPI; } public void setOpenAPI(OpenAPI openAPI) { this.openAPI = openAPI; } public SwaggerConfiguration openAPI(OpenAPI openAPI) { this.openAPI = openAPI; return this; } public String getReaderClass() { return readerClass; } public void setReaderClass(String readerClass) { this.readerClass = readerClass; } public String getScannerClass() { return scannerClass; } public void setScannerClass(String scannerClass) { this.scannerClass = scannerClass; } public Map getUserDefinedOptions() { return userDefinedOptions; } public void setUserDefinedOptions(Map userDefinedOptions) { this.userDefinedOptions = userDefinedOptions; } public SwaggerConfiguration scannerClass(String scannerClass) { this.scannerClass = scannerClass; return this; } public SwaggerConfiguration readerClass(String readerClass) { this.readerClass = readerClass; return this; } public SwaggerConfiguration userDefinedOptions(Map userDefinedOptions) { this.userDefinedOptions = userDefinedOptions; return this; } @Override public Set getResourcePackages() { return resourcePackages; } public void setResourcePackages(Set resourcePackages) { this.resourcePackages = resourcePackages; } public SwaggerConfiguration resourcePackages(Set resourcePackages) { this.resourcePackages = resourcePackages; return this; } public Set getResourceClasses() { return resourceClasses; } public void setResourceClasses(Set resourceClasses) { this.resourceClasses = resourceClasses; } public SwaggerConfiguration resourceClasses(Set resourceClasses) { this.resourceClasses = resourceClasses; return this; } public String getFilterClass() { return filterClass; } public void setFilterClass(String filterClass) { this.filterClass = filterClass; } public SwaggerConfiguration filterClass(String filterClass) { this.filterClass = filterClass; return this; } public SwaggerConfiguration id(String id) { this.id = id; return this; } public String getId() { return id; } public void setId(String id) { this.id = id; } /** * @since 2.0.6 */ public SwaggerConfiguration objectMapperProcessorClass(String objectMapperProcessorClass) { this.objectMapperProcessorClass = objectMapperProcessorClass; return this; } /** * @since 2.0.6 */ public String getObjectMapperProcessorClass() { return objectMapperProcessorClass; } /** * @since 2.0.6 */ public void setObjectMapperProcessorClass(String objectMapperProcessorClass) { this.objectMapperProcessorClass = objectMapperProcessorClass; } /** * @since 2.0.6 */ public Set getModelConverterClasses() { return modelConverterClasses; } /** * @since 2.0.6 */ public void setModelConverterClassess(Set modelConverterClasses) { this.modelConverterClasses = modelConverterClasses; } /** * @since 2.0.6 */ public SwaggerConfiguration modelConverterClasses(Set modelConverterClasses) { this.modelConverterClasses = modelConverterClasses; return this; } /** * @since 2.1.6 */ @Override public Boolean isSortOutput() { return sortOutput; } /** * @since 2.1.6 */ public void setSortOutput(Boolean sortOutput) { this.sortOutput = sortOutput; } /** * @since 2.1.6 */ public SwaggerConfiguration sortOutput(Boolean sortOutput) { setSortOutput(sortOutput); return this; } /** * @since 2.1.9 */ @Override public Boolean isAlwaysResolveAppPath() { return alwaysResolveAppPath; } /** * @since 2.1.9 */ public void setAlwaysResolveAppPath(Boolean alwaysResolveAppPath) { this.alwaysResolveAppPath = alwaysResolveAppPath; } /** * @since 2.1.9 */ public SwaggerConfiguration alwaysResolveAppPath(Boolean alwaysResolveAppPath) { setAlwaysResolveAppPath(alwaysResolveAppPath); return this; } /** * @since 2.1.15 */ @Override public Boolean isSkipResolveAppPath() { return skipResolveAppPath; } /** * @since 2.1.15 */ public void setSkipResolveAppPath(Boolean skipResolveAppPath) { this.skipResolveAppPath = skipResolveAppPath; } /** * @since 2.1.15 */ public SwaggerConfiguration skipResolveAppPath(Boolean skipResolveAppPath) { setSkipResolveAppPath(skipResolveAppPath); return this; } /** * @since 2.1.9 */ public Boolean isOpenAPI31() { return openAPI31; } /** * @since 2.1.9 */ public void setOpenAPI31(Boolean openAPI31) { this.openAPI31 = openAPI31; } /** * @since 2.1.9 */ public SwaggerConfiguration openAPI31(Boolean openAPI31) { this.openAPI31 = openAPI31; return this; } /** * @since 2.2.12 */ public Boolean isConvertToOpenAPI31() { return convertToOpenAPI31; } /** * @since 2.2.12 */ public void setConvertToOpenAPI31(Boolean convertToOpenAPI31) { this.convertToOpenAPI31 = convertToOpenAPI31; if (Boolean.TRUE.equals(convertToOpenAPI31)) { this.openAPI31 = true; } } /** * @since 2.2.12 */ public SwaggerConfiguration convertToOpenAPI31(Boolean convertToOpenAPI31) { this.setConvertToOpenAPI31(convertToOpenAPI31); return this; } @Override public Schema.SchemaResolution getSchemaResolution() { return schemaResolution; } public void setSchemaResolution(Schema.SchemaResolution schemaResolution) { this.schemaResolution = schemaResolution; } public SwaggerConfiguration schemaResolution(Schema.SchemaResolution schemaResolution) { this.setSchemaResolution(schemaResolution); return this; } /** * @since 2.2.28 */ @Override public String getOpenAPIVersion() { return openAPIVersion; } /** * @since 2.2.28 */ public void setOpenAPIVersion(String openAPIVersion) { this.openAPIVersion = openAPIVersion; } /** * @since 2.2.28 */ public SwaggerConfiguration openAPIVersion(String openAPIVersion) { this.setOpenAPIVersion(openAPIVersion); return this; } /** * @since 2.2.29 */ @Override public Configuration.GroupsValidationStrategy getGroupsValidationStrategy() { return groupsValidationStrategy; } /** * @since 2.2.29 */ public void setGroupsValidationStrategy(Configuration.GroupsValidationStrategy groupsValidationStrategy) { this.groupsValidationStrategy = groupsValidationStrategy; } /** * @since 2.2.29 */ public SwaggerConfiguration groupsValidationStrategy(Configuration.GroupsValidationStrategy groupsValidationStrategy) { this.groupsValidationStrategy = groupsValidationStrategy; return this; } /** * see io.swagger.v3.core.util.ValidatorProcessor * * @since 2.2.29 */ @Override public String getValidatorProcessorClass() { return validatorProcessorClass; } /** * @since 2.2.29 */ public void setValidatorProcessorClass(String validatorProcessorClass) { this.validatorProcessorClass = validatorProcessorClass; } /** * @since 2.2.29 */ public SwaggerConfiguration validatorProcessorClass(String validatorProcessorClass) { this.validatorProcessorClass = validatorProcessorClass; return this; } public Configuration toConfiguration() { Configuration configuration = new Configuration(); configuration.setOpenAPI(getOpenAPI()); configuration.setUserDefinedOptions(getUserDefinedOptions()); configuration.setModelConverterClasses(getModelConverterClasses()); configuration.setObjectMapperProcessorClass(getObjectMapperProcessorClass()); configuration.setOpenAPI31(isOpenAPI31()); configuration.setSchemaResolution(getSchemaResolution()); configuration.setOpenAPIVersion(getOpenAPIVersion()); configuration.setGroupsValidationStrategy(getGroupsValidationStrategy()); configuration.setValidatorProcessorClass(getValidatorProcessorClass()); return configuration; } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/URLOpenApiConfigurationLoader.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiConfigurationLoader; import java.io.IOException; // TODO public class URLOpenApiConfigurationLoader implements OpenApiConfigurationLoader { @Override public OpenAPIConfiguration load(String path) throws IOException { return null; } @Override public boolean exists(String path) { return false; } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/ObjectMapperProcessor.java ================================================ package io.swagger.v3.oas.integration.api; import com.fasterxml.jackson.databind.ObjectMapper; /** * @since 2.0.6 */ public interface ObjectMapperProcessor { default void processJsonObjectMapper(ObjectMapper mapper) {}; /** * @deprecated since 2.0.7, as no-op * */ @Deprecated default void processYamlObjectMapper(ObjectMapper mapper) {} /** * @since 2.1.6 */ default void processOutputJsonObjectMapper(ObjectMapper mapper) {} /** * @since 2.1.6 */ default void processOutputYamlObjectMapper(ObjectMapper mapper) { processOutputJsonObjectMapper(mapper); } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenAPIConfigBuilder.java ================================================ package io.swagger.v3.oas.integration.api; public interface OpenAPIConfigBuilder { OpenAPIConfiguration build(); } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenAPIConfiguration.java ================================================ package io.swagger.v3.oas.integration.api; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import java.util.Collection; import java.util.Map; import java.util.Set; public interface OpenAPIConfiguration { Set getResourcePackages(); Set getResourceClasses(); String getReaderClass(); String getScannerClass(); String getFilterClass(); Collection getIgnoredRoutes(); OpenAPI getOpenAPI(); Map getUserDefinedOptions(); Boolean isReadAllResources(); Boolean isPrettyPrint(); Long getCacheTTL(); /** * @since 2.0.6 */ public String getObjectMapperProcessorClass(); /** * @since 2.0.6 */ public Set getModelConverterClasses(); /** * @since 2.1.6 */ Boolean isSortOutput(); /** * @since 2.1.9 */ Boolean isAlwaysResolveAppPath(); /** * @since 2.1.15 */ Boolean isSkipResolveAppPath(); /** * @since 2.2.12 */ Boolean isOpenAPI31(); /** * @since 2.2.12 */ Boolean isConvertToOpenAPI31(); /** * @since 2.2.17 */ public String getDefaultResponseCode(); /** * @since 2.2.24 */ public Schema.SchemaResolution getSchemaResolution(); /** * @since 2.2.28 */ public String getOpenAPIVersion(); /** * @since 2.2.29 */ public String getValidatorProcessorClass(); /** * @since 2.2.29 */ public Configuration.GroupsValidationStrategy getGroupsValidationStrategy(); /** * @since 2.2.29 */ public Configuration toConfiguration(); } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenApiConfigurationLoader.java ================================================ package io.swagger.v3.oas.integration.api; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public interface OpenApiConfigurationLoader { OpenAPIConfiguration load(String path) throws IOException; boolean exists(String path); default String readInputStreamToString(InputStream stream) throws IOException { StringBuilder sb = new StringBuilder(); try (BufferedReader in = new BufferedReader( new InputStreamReader(stream))) { String inputLine; while ((inputLine = in.readLine()) != null) { sb.append(inputLine).append("\n"); } } return sb.toString(); } } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenApiContext.java ================================================ package io.swagger.v3.oas.integration.api; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.oas.integration.OpenApiConfigurationException; import io.swagger.v3.oas.models.OpenAPI; import java.util.Set; public interface OpenApiContext { String OPENAPI_CONTEXT_ID_KEY = "openapi.context.id"; String OPENAPI_CONTEXT_ID_PREFIX = OPENAPI_CONTEXT_ID_KEY + "."; String OPENAPI_CONTEXT_ID_DEFAULT = OPENAPI_CONTEXT_ID_PREFIX + "default"; String getId(); OpenApiContext init() throws OpenApiConfigurationException; OpenAPI read(); OpenAPIConfiguration getOpenApiConfiguration(); String getConfigLocation(); OpenApiContext getParent(); void setOpenApiScanner(OpenApiScanner openApiScanner); void setOpenApiReader(OpenApiReader openApiReader); /** * @since 2.0.6 */ void setObjectMapperProcessor(ObjectMapperProcessor objectMapperProcessor); /** * @since 2.0.6 */ void setModelConverters(Set modelConverters); /** * @since 2.1.6 */ ObjectMapper getOutputJsonMapper(); /** * @since 2.1.6 */ ObjectMapper getOutputYamlMapper(); /** * @since 2.1.6 */ void setOutputJsonMapper(ObjectMapper outputJsonMapper); /** * @since 2.1.6 */ void setOutputYamlMapper(ObjectMapper outputYamlMapper); } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenApiContextBuilder.java ================================================ package io.swagger.v3.oas.integration.api; import io.swagger.v3.oas.integration.OpenApiConfigurationException; public interface OpenApiContextBuilder { OpenApiContext buildContext(boolean init) throws OpenApiConfigurationException; } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenApiReader.java ================================================ package io.swagger.v3.oas.integration.api; import io.swagger.v3.oas.models.OpenAPI; import java.util.Map; import java.util.Set; public interface OpenApiReader { void setConfiguration(OpenAPIConfiguration openApiConfiguration); OpenAPI read(Set> classes, Map resources); } ================================================ FILE: modules/swagger-integration/src/main/java/io/swagger/v3/oas/integration/api/OpenApiScanner.java ================================================ package io.swagger.v3.oas.integration.api; import java.util.Map; import java.util.Set; public interface OpenApiScanner { void setConfiguration(OpenAPIConfiguration openApiConfiguration); Set> classes(); Map resources(); } ================================================ FILE: modules/swagger-integration/src/test/java/io/swagger/v3/oas/integration/IntegrationTest.java ================================================ package io.swagger.v3.oas.integration; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import org.testng.annotations.Test; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import static org.testng.Assert.assertNotNull; public class IntegrationTest { // TODO after implementation of generic reader and possibly generic scanner if we reintroduce "api" or similar annotation private final Set expectedKeys = new HashSet(Arrays.asList("/packageA", "/packageB")); @Test(description = "initialize a context and read") public void shouldInitialize() throws Exception { OpenAPIConfiguration config = new SwaggerConfiguration() .resourcePackages(Stream.of("com.my.project.resources", "org.my.project.resources").collect(Collectors.toSet())) .openAPI(new OpenAPI().info(new Info().description("TEST INFO DESC"))); OpenApiContext ctx = new GenericOpenApiContext() .openApiConfiguration(config) .init(); OpenAPI openApi = ctx.read(); assertNotNull(openApi); } } ================================================ FILE: modules/swagger-java17-support/pom.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-project 2.2.46-SNAPSHOT ../../pom.xml swagger-java17-support jar swagger-java17-support Module for Java 17 specific tests org.testng testng test io.swagger.core.v3 swagger-jaxrs2 ${project.version} io.swagger.core.v3 swagger-core ${project.version} io.swagger.core.v3 swagger-annotations ${project.version} io.swagger.core.v3 swagger-models ${project.version} org.glassfish.jersey.media jersey-media-multipart ${jersey2-version} test javax.annotation javax.annotation-api org.javassist javassist org.glassfish.jersey.inject jersey-hk2 ${jersey2-version} test javax.annotation javax.annotation-api org.javassist javassist org.apache.maven.plugins maven-compiler-plugin 3.11.0 17 17 ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/ReaderTest.java ================================================ package io.swagger.v3.java17.Reader; import io.swagger.v3.java17.matchers.SerializationMatchers; import io.swagger.v3.java17.resources.JavaRecordWithPathResource; import io.swagger.v3.java17.resources.OtherJavaRecordWithPathsResource; import io.swagger.v3.java17.resources.TestControllerWithRecordResource; import io.swagger.v3.jaxrs2.Reader; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.OpenAPI; import org.testng.annotations.Test; import java.util.HashSet; import java.util.Set; public class ReaderTest { @Test public void TestJavaRecordRef(){ Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); OpenAPI openAPI = reader.read(TestControllerWithRecordResource.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /v17:\n" + " post:\n" + " operationId: opsRecordID\n" + " responses:\n" + " default:\n" + " description: Successful operation\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: '#/components/schemas/JavaRecordResource'\n" + "components:\n" + " schemas:\n" + " JavaRecordResource:\n" + " type: object\n" + " properties:\n" + " test:\n" + " type: string\n" + " description: Testing of Java Record Processing\n" + " isLatest:\n" + " type: boolean\n" + " id:\n" + " type: string\n" + " age:\n" + " type: integer\n" + " format: int32"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void TestSetOfRecords(){ Set> classes = new HashSet<>(); classes.add(JavaRecordWithPathResource.class); classes.add(OtherJavaRecordWithPathsResource.class); Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(classes); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /sample/1:\n" + " post:\n" + " description: description 1\n" + " operationId: id 1\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /sample/2:\n" + " post:\n" + " description: description 2\n" + " operationId: id 2\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /sample2:\n" + " get:\n" + " description: description\n" + " operationId: Operation Id\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " security:\n" + " - security_key:\n" + " - write:pets\n" + " - read:pets\n" + " /sample2/2:\n" + " get:\n" + " description: description 2\n" + " operationId: Operation Id 2\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " security:\n" + " - security_key2:\n" + " - write:pets\n" + " - read:pets"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/Reader/SchemaResolutionRecordsTest.java ================================================ package io.swagger.v3.java17.Reader; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.java17.matchers.SerializationMatchers; import io.swagger.v3.java17.resources.SchemaResolutionWithRecordSimpleResource; import io.swagger.v3.java17.resources.SchemaResolutionWithRecordsResource; import io.swagger.v3.jaxrs2.Reader; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class SchemaResolutionRecordsTest { @Test public void testSchemaResolutionInlineWithRecords(){ ModelConverters.reset(); Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.INLINE)); OpenAPI openAPI = reader.read(SchemaResolutionWithRecordsResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/inlineSchemaFirst:\n" + " get:\n" + " operationId: inlineSchemaFirst\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " /test/inlineSchemaSecond:\n" + " get:\n" + " operationId: inlineSchemaSecond\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n" + " description: InlineSchemaSecond property 1\n" + " nullable: true\n" + " example: exampleSecond\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: InlineSchemaSecond property 2\n" + " nullable: true\n" + " example: example\n" + " description: InlineSchemaSecond API\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n" + " description: InlineSchemaSecond property 1\n" + " nullable: true\n" + " example: exampleSecond\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: InlineSchemaSecond property 2\n" + " nullable: true\n" + " example: example\n" + "components:\n" + " schemas:\n" + " InlineSchemaPropertyFirst:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " nullable: true\n" + " example: example\n" + " InlineSchemaRecordFirst:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " InlineSchemaPropertySecond:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n" + " description: propertySecond\n" + " nullable: true\n" + " example: exampleSecond\n" + " InlineSchemaPropertySimple:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " InlineSchemaRecordSecond:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n" + " description: InlineSchemaSecond property 1\n" + " nullable: true\n" + " example: exampleSecond\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: InlineSchemaSecond property 2\n" + " nullable: true\n" + " example: example\n" + " description: InlineSchemaSecond API\n" + " InlineSchemaSimple:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test public void testSchemaResolutionAllOfWithRecordTest(){ ModelConverters.reset(); Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.ALL_OF)); OpenAPI openAPI = reader.read(SchemaResolutionWithRecordSimpleResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/inlineSchemaFirst:\n" + " get:\n" + " operationId: inlineSchemaFirst\n" + " responses:\n" + " default:\n" + " description: InlineSchemaFirst Response API\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: '#/components/schemas/SchemaRecordFirst'\n" + " /test/inlineSchemaSecond:\n" + " get:\n" + " operationId: inlineSchemaFirst_1\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " allOf:\n" + " - description: InlineSchemaSecond API\n" + " - $ref: '#/components/schemas/SchemaRecordFirst'\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " InlineSchemaPropertyFirst:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " nullable: true\n" + " example: example\n" + " SchemaRecordFirst:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test public void testSchemaResolutionAllOfRefWithRecordsTest(){ ModelConverters.reset(); Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.ALL_OF_REF)); OpenAPI openAPI = reader.read(SchemaResolutionWithRecordsResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/inlineSchemaFirst:\n" + " get:\n" + " operationId: inlineSchemaFirst\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: '#/components/schemas/InlineSchemaRecordFirst'\n" + " /test/inlineSchemaSecond:\n" + " get:\n" + " operationId: inlineSchemaSecond\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " description: InlineSchemaSecond API\n" + " allOf:\n" + " - $ref: '#/components/schemas/InlineSchemaRecordSecond'\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: '#/components/schemas/InlineSchemaRecordSecond'\n" + "components:\n" + " schemas:\n" + " InlineSchemaPropertyFirst:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " InlineSchemaRecordFirst:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + " property2:\n" + " $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + " InlineSchemaPropertySecond:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " $ref: '#/components/schemas/InlineSchemaSimple'\n" + " description: propertySecond\n" + " example: exampleSecond\n" + " InlineSchemaPropertySimple:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " InlineSchemaRecordSecond:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " description: InlineSchemaSecond property 1\n" + " nullable: true\n" + " allOf:\n" + " - $ref: '#/components/schemas/InlineSchemaPropertySecond'\n" + " property2:\n" + " description: InlineSchemaSecond property 2\n" + " nullable: true\n" + " allOf:\n" + " - $ref: '#/components/schemas/InlineSchemaPropertyFirst'\n" + " InlineSchemaSimple:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " description: property 1\n" + " allOf:\n" + " - $ref: '#/components/schemas/InlineSchemaPropertySimple'\n" + " property2:\n" + " description: property 2\n" + " example: example\n" + " allOf:\n" + " - $ref: '#/components/schemas/InlineSchemaPropertySimple'\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/matchers/SerializationMatchers.java ================================================ package io.swagger.v3.java17.matchers; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.NumericNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Comparator; import static org.testng.Assert.assertEquals; public class SerializationMatchers { private static final Logger LOGGER = LoggerFactory.getLogger(SerializationMatchers.class); public static void assertEqualsToYaml(Object objectToSerialize, String yamlStr) { apply(objectToSerialize, yamlStr, Yaml.mapper(), false); } public static void assertEqualsToYamlExact(Object objectToSerialize, String yamlStr) { apply(objectToSerialize, yamlStr, Yaml.mapper(), true); } public static void assertEqualsToJson(Object objectToSerialize, String jsonStr) { apply(objectToSerialize, jsonStr, Json.mapper(), false); } public static void assertEqualsToYaml31(Object objectToSerialize, String yamlStr) { apply31(objectToSerialize, yamlStr, Yaml31.mapper()); } public static void assertEqualsToJson31(Object objectToSerialize, String jsonStr) { apply31(objectToSerialize, jsonStr, Json31.mapper()); } private static void apply(Object objectToSerialize, String str, ObjectMapper mapper, boolean exactMatch) { final ObjectNode lhs = mapper.convertValue(objectToSerialize, ObjectNode.class); ObjectNode rhs = null; try { rhs = mapper.readValue(str, ObjectNode.class); } catch (IOException e) { LOGGER.error("Failed to read value", e); } if (exactMatch || !lhs.equals(new ObjectNodeComparator(), rhs)) { assertEquals(Yaml.pretty(lhs), Yaml.pretty(rhs)); //fail(String.format("Serialized object:\n%s\ndoes not equal to expected serialized string:\n%s", lhs, rhs)); } } private static void apply31(Object objectToSerialize, String str, ObjectMapper mapper) { final ObjectNode lhs = mapper.convertValue(objectToSerialize, ObjectNode.class); ObjectNode rhs = null; try { rhs = mapper.readValue(str, ObjectNode.class); } catch (IOException e) { LOGGER.error("Failed to read value", e); } if (!lhs.equals(new ObjectNodeComparator(), rhs)) { assertEquals(Yaml31.pretty(lhs), Yaml31.pretty(rhs)); } } static final class ObjectNodeComparator implements Comparator { @Override public int compare(JsonNode o1, JsonNode o2) { if (o1.equals(o2)) { return 0; } if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)) { double d1 = ((NumericNode) o1).asDouble(); double d2 = ((NumericNode) o2).asDouble(); return Double.compare(d1, d2); } int comp = o1.asText().compareTo(o2.asText()); if (comp == 0) { return Integer.compare(o1.hashCode(), o2.hashCode()); } return comp; } } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/JavaRecordTest.java ================================================ package io.swagger.v3.java17.resolving; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.java17.matchers.SerializationMatchers; import org.testng.annotations.Test; import javax.validation.constraints.*; import java.util.List; import java.util.Map; public class JavaRecordTest { @Test public void testJavaRecordWithSchema() { String expectedYaml = "JavaRecordClassWithSchema:\n" + " type: object\n" + " description: Java Record with Schema Test\n" + " properties:\n" + " test:\n" + " type: string\n" + " description: Testing of Schema on fields processing in Java Records\n" + " isLatest:\n" + " type: boolean"; Map stringSchemaMap = ModelConverters.getInstance(false).readAll(JavaRecordClassWithSchema.class); SerializationMatchers.assertEqualsToYaml(stringSchemaMap, expectedYaml); } @Test public void testJavaRecordWithBeanValidation() { String expectedYaml = "JavaRecordClassWithBeanValidation:\n" + " type: object\n" + " description: Java Record with Bean Validation Test\n" + " properties:\n" + " test:\n" + " maxLength: 100\n" + " minLength: 1\n" + " type: string\n" + " isLatest:\n" + " type: boolean\n" + " randomList:\n" + " maxItems: 101\n" + " minItems: 2\n" + " type: array\n" + " items:\n" + " type: string\n" + " myField:\n" + " maximum: 100\n" + " exclusiveMaximum: false\n" + " minimum: 1\n" + " exclusiveMinimum: false\n" + " type: number\n" + " email:\n" + " pattern: (.+?)@(.+?)\n" + " type: string"; Map stringSchemaMap = ModelConverters.getInstance(false).readAll(JavaRecordClassWithBeanValidation.class); SerializationMatchers.assertEqualsToYaml(stringSchemaMap, expectedYaml); } @io.swagger.v3.oas.annotations.media.Schema(description = "Java Record with Schema Test") public record JavaRecordClassWithSchema( @io.swagger.v3.oas.annotations.media.Schema(description = "Testing of Schema on fields processing in Java Records") String test, boolean isLatest ){ } @io.swagger.v3.oas.annotations.media.Schema(description = "Java Record with Bean Validation Test") public record JavaRecordClassWithBeanValidation( @Size(min = 1, max = 100) String test, boolean isLatest, @Size(min = 2, max = 101) List randomList, @DecimalMin("1") @DecimalMax("100") Number myField, @Pattern(regexp = "(.+?)@(.+?)") String email ){ } @Test public void testJavaRecordWithBeanValidationSizeTypeUse() { String expectedYaml = "JavaRecordWithAnnotationsOnGenericType:\n" + " type: object\n" + " properties:\n" + " randomList:\n" + " maxItems: 10000\n" + " minItems: 100\n" + " type: array\n" + " items:\n" + " maxLength: 10\n" + " minLength: 1\n" + " type: string\n" + " secondList:\n" + " type: array\n" + " items:\n" + " pattern: (.+?)@(.+?)\n" + " type: string\n" + " id:\n" + " type: array\n" + " items:\n" + " maximum: 10000\n" + " minimum: 1\n" + " type: integer\n" + " format: int32"; Map stringSchemaMap = ModelConverters.getInstance(false).readAll(JavaRecordWithAnnotationsOnGenericType.class); SerializationMatchers.assertEqualsToYaml(stringSchemaMap, expectedYaml); } public record JavaRecordWithAnnotationsOnGenericType( @Size(min = 100, max = 10000) List<@Size(min = 1, max = 10) String> randomList, List<@Pattern(regexp = "(.+?)@(.+?)") String> secondList, List<@Min(1)@Max(10000) Integer> id ){ } @Test public void testJavaRecordWithJsonPropertyAnnotationNotMatchingFieldName() { String expectedYaml = "JavaRecordWithJsonPropertyAnnotationNotMatchingFieldName:\n" + " type: object\n" + " properties:\n" + " listOfStrings:\n" + " type: array\n" + " items:\n" + " maxLength: 5\n" + " minLength: 1\n" + " type: string"; Map stringSchemaMap = ModelConverters.getInstance(false).readAll(JavaRecordWithJsonPropertyAnnotationNotMatchingFieldName.class); SerializationMatchers.assertEqualsToYaml(stringSchemaMap, expectedYaml); } public record JavaRecordWithJsonPropertyAnnotationNotMatchingFieldName( @JsonProperty("listOfStrings") List<@Size(min = 1, max = 5)String> stringList ) { } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/SwaggerTestBase.java ================================================ package io.swagger.v3.java17.resolving; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import io.swagger.v3.core.jackson.ModelResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class SwaggerTestBase { static ObjectMapper mapper; private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerTestBase.class); public static ObjectMapper mapper() { if (mapper == null) { mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } return mapper; } protected ModelResolver modelResolver() { return new ModelResolver(new ObjectMapper()); } protected void prettyPrint(Object o) { try { LOGGER.debug(mapper().writer(new DefaultPrettyPrinter()).writeValueAsString(o)); } catch (Exception e) { LOGGER.error("Failed to pretty print object", e); } } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resolving/v31/ModelResolverOAS31Test.java ================================================ package io.swagger.v3.java17.resolving.v31; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.java17.resolving.SwaggerTestBase; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; import io.swagger.v3.java17.matchers.SerializationMatchers; import java.util.List; import java.util.Map; public class ModelResolverOAS31Test extends SwaggerTestBase { @Test public void testOAS31JavaRecord() { String expectedYaml = "JavaRecordWithOAS31Fields:\n" + " type: object\n" + " $comment: Random comment at schema level\n" + " $id: http://yourdomain.com/schemas/myschema.json\n" + " description: this is model for testing OAS 3.1 Java Record resolving\n" + " properties:\n" + " test:\n" + " type: string\n" + " isLatest:\n" + " type: boolean\n" + " randomList:\n" + " type: array\n" + " contains:\n" + " type: string\n" + " items:\n" + " type: string\n" + " maxContains: 10\n" + " minContains: 1\n" + " prefixItems:\n" + " - type: string\n" + " unevaluatedItems:\n" + " type: number\n" + " Status:\n" + " type:\n" + " - string\n" + " - number\n"; Map stringSchemaMap = ModelConverters.getInstance(true).readAll(JavaRecordWithOAS31Fields.class); SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml); } @io.swagger.v3.oas.annotations.media.Schema( $id = "http://yourdomain.com/schemas/myschema.json", description = "this is model for testing OAS 3.1 Java Record resolving", $comment = "Random comment at schema level", types = "object" ) private record JavaRecordWithOAS31Fields( String test, boolean isLatest, @ArraySchema( maxContains = 10, minContains = 1, contains = @io.swagger.v3.oas.annotations.media.Schema( types = "string" ), unevaluatedItems = @io.swagger.v3.oas.annotations.media.Schema( types = "number" ), prefixItems = { @io.swagger.v3.oas.annotations.media.Schema( types = "string" ) } ) List randomList, @io.swagger.v3.oas.annotations.media.Schema(types = { "string", "number" }) Object Status ){ } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordResource.java ================================================ package io.swagger.v3.java17.resources; public record JavaRecordResource( @io.swagger.v3.oas.annotations.media.Schema(description = "Testing of Java Record Processing") String test, boolean isLatest, String id, Integer age ) { } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/JavaRecordWithPathResource.java ================================================ package io.swagger.v3.java17.resources; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.POST; import javax.ws.rs.Path; @Path("sample") public record JavaRecordWithPathResource() { @POST @Path("/1") @Operation(description = "description 1", operationId = "id 1") public void postExample(){ } @POST @Path("/2") @Operation(description = "description 2", operationId = "id 2") public void postExample2(){ } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/OtherJavaRecordWithPathsResource.java ================================================ package io.swagger.v3.java17.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.*; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("sample2") public record OtherJavaRecordWithPathsResource() { @GET @Path("/") @Operation(operationId = "Operation Id", description = "description") @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) public void getSecurity() { } @GET @Path("/2") @Operation(operationId = "Operation Id 2", description = "description 2") @SecurityRequirement(name = "security_key2", scopes = {"write:pets", "read:pets"} ) public void getSecurity2() { } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordSimpleResource.java ================================================ package io.swagger.v3.java17.resources; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @Path("test") public class SchemaResolutionWithRecordSimpleResource{ @GET @Path("/inlineSchemaFirst") @ApiResponse(description = "InlineSchemaFirst Response API", content = @Content(schema = @Schema(implementation = SchemaRecordFirst.class))) public Response inlineSchemaFirst() { return null; } @GET @Path("/inlineSchemaSecond") public void inlineSchemaFirst(@Schema(description = "InlineSchemaSecond API") SchemaRecordFirst inlineSchemaFirst) { } public record SchemaRecordFirst ( @Schema(description = "InlineSchemaFirst property 1", nullable = true) InlineSchemaPropertyFirst property1 ){ } @Schema(description = "property", example = "example") static class InlineSchemaPropertyFirst { public String bar; } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/SchemaResolutionWithRecordsResource.java ================================================ package io.swagger.v3.java17.resources; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("test") public class SchemaResolutionWithRecordsResource { @GET @Path("/inlineSchemaSecond") public InlineSchemaRecordSecond inlineSchemaSecond(@Schema(description = "InlineSchemaSecond API") InlineSchemaRecordSecond inlineSchemaSecond) { return null; } @GET @Path("/inlineSchemaFirst") public InlineSchemaRecordFirst inlineSchemaFirst() { return null; } public record InlineSchemaRecordFirst( InlineSchemaPropertyFirst property1, InlineSchemaPropertyFirst property2 ){ } public record InlineSchemaRecordSecond ( String foo, @Schema(description = "InlineSchemaSecond property 1", nullable = true) InlineSchemaPropertySecond propertySecond1, @Schema(description = "InlineSchemaSecond property 2", nullable = true) InlineSchemaPropertyFirst property2 ){ } @Schema(description = "property", example = "example") static class InlineSchemaPropertyFirst { public String bar; } @Schema(description = "propertySecond", example = "exampleSecond") static class InlineSchemaPropertySecond { public InlineSchemaSimple bar; } static class InlineSchemaSimple { @Schema(description = "property 1") public InlineSchemaPropertySimple property1; private InlineSchemaPropertySimple property2; @Schema(description = "property 2", example = "example") public InlineSchemaPropertySimple getProperty2() { return null; } } @Schema(description = "property") static class InlineSchemaPropertySimple { public String bar; } } ================================================ FILE: modules/swagger-java17-support/src/test/java/io/swagger/v3/java17/resources/TestControllerWithRecordResource.java ================================================ package io.swagger.v3.java17.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; @Path("/v17") public class TestControllerWithRecordResource { @POST @Operation( operationId = "opsRecordID", responses = @ApiResponse(description = "Successful operation", content = @Content(mediaType = "application/json",schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = JavaRecordResource.class)) ) ) @Consumes({"application/json", "application/xml"}) public void postRecord(){} } ================================================ FILE: modules/swagger-jaxrs2/pom.xml ================================================ swagger-project io.swagger.core.v3 2.2.46-SNAPSHOT ../../ 4.0.0 swagger-jaxrs2 swagger-jaxrs2 swagger-jaxrs2 src/main/java install src/test/resources biz.aQute.bnd bnd-maven-plugin org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF io.swagger.v3.jaxrs2 org.codehaus.mojo build-helper-maven-plugin 3.5.0 jetty.port jetty.port.stop reserve-port pre-integration-test reserve-network-port org.eclipse.jetty jetty-maven-plugin 10 ${jetty.port} a ${jetty.port.stop} jar true ${project.basedir}/src/test/webapp start-jetty pre-integration-test start 0 stop-jetty post-integration-test stop org.apache.maven.plugins maven-surefire-plugin ${surefire-version} -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 --add-opens java.base/java.lang=ALL-UNNAMED 0 org.apache.maven.plugins maven-failsafe-plugin ${failsafe-plugin-version} --add-opens java.base/java.lang=ALL-UNNAMED integration-test verify ${jetty.port} jakarta.ws.rs jakarta.ws.rs-api provided jakarta.servlet jakarta.servlet-api provided ch.qos.logback logback-classic provided ch.qos.logback logback-core provided com.fasterxml.jackson.core jackson-databind io.github.classgraph classgraph org.javassist javassist 3.30.2-GA commons-io commons-io io.swagger.core.v3 swagger-models ${project.version} org.yaml snakeyaml ${snakeyaml-version} io.swagger.core.v3 swagger-annotations ${project.version} io.swagger.core.v3 swagger-integration ${project.version} org.testng testng test org.apache.httpcomponents httpmime test io.rest-assured rest-assured test javax.xml.bind jaxb-api org.apache.httpcomponents httpmime org.mockito mockito-core test org.jboss.weld weld-core-impl 3.1.9.Final test org.jboss.arquillian.testng arquillian-testng-container 1.9.3.Final test org.jboss.arquillian.container arquillian-weld-embedded 2.1.0.Final test org.jboss.arquillian.container arquillian-container-spi org.jboss.arquillian.container arquillian-container-test-spi org.jboss.arquillian.test arquillian-test-spi org.glassfish.jersey.containers jersey-container-servlet ${jersey2-version} test javax.annotation javax.annotation-api org.javassist javassist org.glassfish.jersey.media jersey-media-multipart ${jersey2-version} test javax.annotation javax.annotation-api org.javassist javassist org.glassfish.jersey.inject jersey-hk2 ${jersey2-version} test javax.annotation javax.annotation-api org.javassist javassist com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider ${jackson-version} ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/DefaultParameterExtension.java ================================================ package io.swagger.v3.jaxrs2; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.AnnotatedField; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotationMap; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.ParameterProcessor; import io.swagger.v3.jaxrs2.ext.AbstractOpenAPIExtension; import io.swagger.v3.jaxrs2.ext.OpenAPIExtension; import io.swagger.v3.jaxrs2.ext.OpenAPIExtensions; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.parameters.Parameter; import org.apache.commons.lang3.StringUtils; import javax.ws.rs.BeanParam; import javax.ws.rs.CookieParam; import javax.ws.rs.HeaderParam; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.MatrixParam; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; public class DefaultParameterExtension extends AbstractOpenAPIExtension { private static final String QUERY_PARAM = "query"; private static final String HEADER_PARAM = "header"; private static final String COOKIE_PARAM = "cookie"; private static final String PATH_PARAM = "path"; final ObjectMapper mapper = Json.mapper(); @Override public ResolvedParameter extractParameters(List annotations, Type type, Set typesToSkip, Components components, javax.ws.rs.Consumes classConsumes, javax.ws.rs.Consumes methodConsumes, boolean includeRequestBody, JsonView jsonViewAnnotation, Iterator chain) { if (shouldIgnoreType(type, typesToSkip)) { return new ResolvedParameter(); } Parameter parameter = null; for (Annotation annotation : annotations) { if (annotation instanceof QueryParam) { QueryParam param = (QueryParam) annotation; Parameter qp = new Parameter(); qp.setIn(QUERY_PARAM); qp.setName(param.value()); parameter = qp; } else if (annotation instanceof PathParam) { PathParam param = (PathParam) annotation; Parameter pp = new Parameter(); pp.setIn(PATH_PARAM); pp.setName(param.value()); parameter = pp; } else if (annotation instanceof MatrixParam) { MatrixParam param = (MatrixParam) annotation; Parameter pp = new Parameter(); pp.setIn(PATH_PARAM); pp.setStyle(Parameter.StyleEnum.MATRIX); pp.setName(param.value()); parameter = pp; } else if (annotation instanceof HeaderParam) { HeaderParam param = (HeaderParam) annotation; Parameter pp = new Parameter(); pp.setIn(HEADER_PARAM); pp.setName(param.value()); parameter = pp; } else if (annotation instanceof CookieParam) { CookieParam param = (CookieParam) annotation; Parameter pp = new Parameter(); pp.setIn(COOKIE_PARAM); pp.setName(param.value()); parameter = pp; } else if (annotation instanceof io.swagger.v3.oas.annotations.Parameter) { if (((io.swagger.v3.oas.annotations.Parameter) annotation).hidden()) { return new ResolvedParameter(); } if (parameter == null) { parameter = new Parameter(); } if (StringUtils.isNotBlank(((io.swagger.v3.oas.annotations.Parameter) annotation).ref())) { parameter.$ref(((io.swagger.v3.oas.annotations.Parameter) annotation).ref()); } } else { List formParameters = new ArrayList<>(); List parameters = new ArrayList<>(); if (handleAdditionalAnnotation(parameters, formParameters, annotation, type, typesToSkip, classConsumes, methodConsumes, components, includeRequestBody, jsonViewAnnotation)) { ResolvedParameter extractParametersResult = new ResolvedParameter(); extractParametersResult.parameters.addAll(parameters); extractParametersResult.formParameters.addAll(formParameters); return extractParametersResult; } } } List parameters = new ArrayList<>(); ResolvedParameter extractParametersResult = new ResolvedParameter(); if (parameter != null && (StringUtils.isNotBlank(parameter.getIn()) || StringUtils.isNotBlank(parameter.get$ref()))) { parameters.add(parameter); } else if (includeRequestBody) { Parameter unknownParameter = ParameterProcessor.applyAnnotations( null, type, annotations, components, classConsumes == null ? new String[0] : classConsumes.value(), methodConsumes == null ? new String[0] : methodConsumes.value(), jsonViewAnnotation, configuration); if (unknownParameter != null) { if (StringUtils.isNotBlank(unknownParameter.getIn()) && !"form".equals(unknownParameter.getIn())) { extractParametersResult.parameters.add(unknownParameter); } else if ("form".equals(unknownParameter.getIn())) { unknownParameter.setIn(null); extractParametersResult.formParameters.add(unknownParameter); } else { // return as request body extractParametersResult.requestBody = unknownParameter; } } } for (Parameter p : parameters) { Parameter processedParameter = ParameterProcessor.applyAnnotations( p, type, annotations, components, classConsumes == null ? new String[0] : classConsumes.value(), methodConsumes == null ? new String[0] : methodConsumes.value(), jsonViewAnnotation, openapi31, this.schemaResolution); if (processedParameter != null) { extractParametersResult.parameters.add(processedParameter); } } return extractParametersResult; } /** * Adds additional annotation processing support * * @param parameters * @param annotation * @param type * @param typesToSkip */ private boolean handleAdditionalAnnotation(List parameters, List formParameters, Annotation annotation, final Type type, Set typesToSkip, javax.ws.rs.Consumes classConsumes, javax.ws.rs.Consumes methodConsumes, Components components, boolean includeRequestBody, JsonView jsonViewAnnotation) { boolean processed = false; if (BeanParam.class.isAssignableFrom(annotation.getClass())) { // Use Jackson's logic for processing Beans final BeanDescription beanDesc = mapper.getSerializationConfig().introspect(constructType(type)); final List properties = beanDesc.findProperties(); for (final BeanPropertyDefinition propDef : properties) { final AnnotatedField field = propDef.getField(); final AnnotatedMethod setter = propDef.getSetter(); final AnnotatedMethod getter = propDef.getGetter(); final List paramAnnotations = new ArrayList<>(); final Iterator extensions = OpenAPIExtensions.chain(); Type paramType = null; // Gather the field's details if (field != null) { paramType = field.getType(); AnnotationMap annotationMap = field.getAllAnnotations(); if (annotationMap != null) { for (final Annotation fieldAnnotation : annotationMap.annotations()) { if (!paramAnnotations.contains(fieldAnnotation)) { paramAnnotations.add(fieldAnnotation); } } } } // Gather the setter's details but only the ones we need if (setter != null) { // Do not set the param class/type from the setter if the values are already identified if (paramType == null) { // paramType will stay null if there is no parameter paramType = setter.getParameterType(0); } AnnotationMap annotationMap = setter.getAllAnnotations(); if (annotationMap != null) { for (final Annotation fieldAnnotation : annotationMap.annotations()) { if (!paramAnnotations.contains(fieldAnnotation)) { paramAnnotations.add(fieldAnnotation); } } } } // Gather the getter's details but only the ones we need if (getter != null) { // Do not set the param class/type from the getter if the values are already identified if (paramType == null) { paramType = getter.getType(); } AnnotationMap annotationMap = getter.getAllAnnotations(); if (annotationMap != null) { for (final Annotation fieldAnnotation : annotationMap.annotations()) { if (!paramAnnotations.contains(fieldAnnotation)) { paramAnnotations.add(fieldAnnotation); } } } } if (paramType == null) { continue; } // skip hidden properties boolean hidden = false; for (Annotation a : paramAnnotations) { if (a instanceof io.swagger.v3.oas.annotations.media.Schema) { if (((io.swagger.v3.oas.annotations.media.Schema) a).hidden()) { hidden = true; break; }; } else if (a instanceof Hidden) { hidden = true; break; } } if (hidden) { continue; } // Re-process all Bean fields and let the default swagger-jaxrs/swagger-jersey-jaxrs processors do their thing ResolvedParameter resolvedParameter = extensions.next().extractParameters( paramAnnotations, paramType, typesToSkip, components, classConsumes, methodConsumes, includeRequestBody, jsonViewAnnotation, extensions); List extractedParameters = resolvedParameter.parameters; for (Parameter p : extractedParameters) { if (p != null) { parameters.add(p); } } List extractedFormParameters = resolvedParameter.formParameters; for (Parameter p : extractedFormParameters) { if (p != null) { formParameters.add(p); } } processed = true; } } return processed; } @Override protected boolean shouldIgnoreClass(Class cls) { return cls.getName().startsWith("javax.ws.rs."); } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/OperationParser.java ================================================ package io.swagger.v3.jaxrs2; import com.fasterxml.jackson.annotation.JsonView; import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import org.apache.commons.lang3.StringUtils; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import java.util.Map; import java.util.Optional; public class OperationParser { public static final String COMPONENTS_REF = Components.COMPONENTS_SCHEMAS_REF; public static Optional getRequestBody(io.swagger.v3.oas.annotations.parameters.RequestBody requestBody, Consumes classConsumes, Consumes methodConsumes, Components components, JsonView jsonViewAnnotation) { return getRequestBody(requestBody, classConsumes, methodConsumes, components, jsonViewAnnotation, false); } public static Optional getRequestBody(io.swagger.v3.oas.annotations.parameters.RequestBody requestBody, Consumes classConsumes, Consumes methodConsumes, Components components, JsonView jsonViewAnnotation, boolean openapi31) { if (requestBody == null) { return Optional.empty(); } RequestBody requestBodyObject = new RequestBody(); boolean isEmpty = true; if (StringUtils.isNotBlank(requestBody.ref())) { requestBodyObject.set$ref(requestBody.ref()); return Optional.of(requestBodyObject); } if (StringUtils.isNotBlank(requestBody.description())) { requestBodyObject.setDescription(requestBody.description()); isEmpty = false; } if (requestBody.required()) { requestBodyObject.setRequired(requestBody.required()); isEmpty = false; } if (requestBody.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, requestBody.extensions()); if (extensions != null) { extensions.forEach(requestBodyObject::addExtension); } isEmpty = false; } if (requestBody.content().length > 0) { isEmpty = false; } if (isEmpty) { return Optional.empty(); } AnnotationsUtils.getContent(requestBody.content(), classConsumes == null ? new String[0] : classConsumes.value(), methodConsumes == null ? new String[0] : methodConsumes.value(), null, components, jsonViewAnnotation, openapi31).ifPresent(requestBodyObject::setContent); return Optional.of(requestBodyObject); } public static Optional getApiResponses(final io.swagger.v3.oas.annotations.responses.ApiResponse[] responses, Produces classProduces, Produces methodProduces, Components components, JsonView jsonViewAnnotation) { return getApiResponses(responses, classProduces, methodProduces, components, jsonViewAnnotation, false, ApiResponses.DEFAULT); } public static Optional getApiResponses(final io.swagger.v3.oas.annotations.responses.ApiResponse[] responses, Produces classProduces, Produces methodProduces, Components components, JsonView jsonViewAnnotation, boolean openapi31, String defaultResponseKey) { if (responses == null) { return Optional.empty(); } ApiResponses apiResponsesObject = new ApiResponses(); for (io.swagger.v3.oas.annotations.responses.ApiResponse response : responses) { ApiResponse apiResponseObject = new ApiResponse(); if (StringUtils.isNotBlank(response.ref())) { apiResponseObject.set$ref(response.ref()); if (StringUtils.isNotBlank(response.responseCode())) { apiResponsesObject.addApiResponse(response.responseCode(), apiResponseObject); } else { apiResponsesObject._default(apiResponseObject); } continue; } if (StringUtils.isNotBlank(response.description())) { apiResponseObject.setDescription(response.description()); } if (response.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, response.extensions()); if (extensions != null) { extensions.forEach(apiResponseObject::addExtension); } } AnnotationsUtils.getContent(response.content(), classProduces == null ? new String[0] : classProduces.value(), methodProduces == null ? new String[0] : methodProduces.value(), null, components, jsonViewAnnotation, openapi31).ifPresent(apiResponseObject::content); AnnotationsUtils.getHeaders(response.headers(), components, jsonViewAnnotation).ifPresent(apiResponseObject::headers); if (StringUtils.isNotBlank(apiResponseObject.getDescription()) || apiResponseObject.getContent() != null || apiResponseObject.getHeaders() != null) { Map links = AnnotationsUtils.getLinks(response.links()); if (links.size() > 0) { apiResponseObject.setLinks(links); } if (StringUtils.isNotBlank(response.responseCode())) { apiResponsesObject.addApiResponse(response.responseCode(), apiResponseObject); } else { apiResponsesObject.addApiResponse(defaultResponseKey, apiResponseObject); } } } if (apiResponsesObject.isEmpty()) { return Optional.empty(); } return Optional.of(apiResponsesObject); } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/Reader.java ================================================ package io.swagger.v3.jaxrs2; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; import com.fasterxml.jackson.databind.type.TypeFactory; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.KotlinDetector; import io.swagger.v3.core.util.ParameterProcessor; import io.swagger.v3.core.util.PathUtils; import io.swagger.v3.core.util.ReflectionUtils; import io.swagger.v3.jaxrs2.ext.OpenAPIExtension; import io.swagger.v3.jaxrs2.ext.OpenAPIExtensions; import io.swagger.v3.jaxrs2.util.ReaderUtils; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.integration.ContextUtils; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiReader; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.Encoding; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.tags.Tag; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ws.rs.ApplicationPath; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.core.Application; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.CompletionStage; import java.util.stream.Collectors; public class Reader implements OpenApiReader { private static final Logger LOGGER = LoggerFactory.getLogger(Reader.class); public static final String DEFAULT_MEDIA_TYPE_VALUE = "*/*"; public static final String DEFAULT_DESCRIPTION = "default response"; protected OpenAPIConfiguration config; private Application application; private OpenAPI openAPI; private Components components; private Paths paths; private Set openApiTags; private String defaultResponseKey = ApiResponses.DEFAULT; private static final String GET_METHOD = "get"; private static final String POST_METHOD = "post"; private static final String PUT_METHOD = "put"; private static final String DELETE_METHOD = "delete"; private static final String PATCH_METHOD = "patch"; private static final String TRACE_METHOD = "trace"; private static final String HEAD_METHOD = "head"; private static final String OPTIONS_METHOD = "options"; public Reader() { this(new OpenAPI(), new Paths(), new LinkedHashSet<>(), new Components()); } public Reader(OpenAPI openAPI) { this(openAPI, new Paths(), new LinkedHashSet<>(), new Components()); } public Reader(OpenAPIConfiguration openApiConfiguration) { this(new OpenAPI(), new Paths(), new LinkedHashSet<>(), new Components(), openApiConfiguration); } protected Reader(OpenAPI openAPI, Paths paths, Set openApiTags, Components components) { this(openAPI, paths, openApiTags, components, new SwaggerConfiguration().openAPI(openAPI)); } protected Reader(OpenAPI openAPI, Paths paths, Set openApiTags, Components components, OpenAPIConfiguration openApiConfiguration) { this.openAPI = openAPI; this.paths = paths; this.openApiTags = openApiTags; this.components = components; setConfiguration(openApiConfiguration); } public OpenAPI getOpenAPI() { return openAPI; } protected Set getOpenApiTags() { return openApiTags; } protected Components getComponents() { return components; } protected Paths getPaths() { return paths; } /** * Scans a single class for Swagger annotations - does not invoke ReaderListeners */ public OpenAPI read(Class cls) { return read(cls, resolveApplicationPath(), null, false, null, null, new LinkedHashSet(), new ArrayList(), new HashSet>()); } /** * Scans a set of classes for both ReaderListeners and OpenAPI annotations. All found listeners will * be instantiated before any of the classes are scanned for OpenAPI annotations - so they can be invoked * accordingly. * * @param classes a set of classes to scan * @return the generated OpenAPI definition */ public OpenAPI read(Set> classes) { Set> sortedClasses = new TreeSet<>((class1, class2) -> { if (class1.equals(class2)) { return 0; } else if (class1.isAssignableFrom(class2)) { return -1; } else if (class2.isAssignableFrom(class1)) { return 1; } return class1.getName().compareTo(class2.getName()); }); sortedClasses.addAll(classes); Map, ReaderListener> listeners = new HashMap<>(); String appPath = ""; for (Class cls : sortedClasses) { if (ReaderListener.class.isAssignableFrom(cls) && !listeners.containsKey(cls)) { try { listeners.put(cls, (ReaderListener) cls.getDeclaredConstructor().newInstance()); } catch (Exception e) { LOGGER.error("Failed to create ReaderListener", e); } } if (config != null && Boolean.TRUE.equals(config.isAlwaysResolveAppPath()) && !Boolean.TRUE.equals(config.isSkipResolveAppPath())) { if (Application.class.isAssignableFrom(cls)) { ApplicationPath appPathAnnotation = ReflectionUtils.getAnnotation(cls, ApplicationPath.class); if (appPathAnnotation != null) { appPath = appPathAnnotation.value(); } } } } for (ReaderListener listener : listeners.values()) { try { listener.beforeScan(this, openAPI); } catch (Exception e) { LOGGER.error("Unexpected error invoking beforeScan listener [" + listener.getClass().getName() + "]", e); } } String appPathRuntime = resolveApplicationPath(); if (StringUtils.isNotBlank(appPathRuntime)) { appPath = appPathRuntime; } for (Class cls : sortedClasses) { read(cls, appPath, null, false, null, null, new LinkedHashSet(), new ArrayList(), new HashSet>()); } for (ReaderListener listener : listeners.values()) { try { listener.afterScan(this, openAPI); } catch (Exception e) { LOGGER.error("Unexpected error invoking afterScan listener [" + listener.getClass().getName() + "]", e); } } return openAPI; } @Override public void setConfiguration(OpenAPIConfiguration openApiConfiguration) { if (openApiConfiguration != null) { this.config = ContextUtils.deepCopy(openApiConfiguration); if (openApiConfiguration.getOpenAPI() != null) { this.openAPI = this.config.getOpenAPI(); if (this.openAPI.getComponents() != null) { this.components = this.openAPI.getComponents(); } } if (StringUtils.isNotBlank(openApiConfiguration.getOpenAPIVersion())) { this.openAPI.openapi(openApiConfiguration.getOpenAPIVersion()); } this.defaultResponseKey = StringUtils.isBlank(config.getDefaultResponseCode()) ? ApiResponses.DEFAULT : config.getDefaultResponseCode(); } } @Override public OpenAPI read(Set> classes, Map resources) { return read(classes); } protected String resolveApplicationPath() { if (application != null && !Boolean.TRUE.equals(config.isSkipResolveAppPath())) { Class applicationToScan = this.application.getClass(); ApplicationPath applicationPath; //search up in the hierarchy until we find one with the annotation, this is needed because for example Weld proxies will not have the annotation and the right class will be the superClass while ((applicationPath = applicationToScan.getAnnotation(ApplicationPath.class)) == null && !applicationToScan.getSuperclass().equals(Application.class)) { applicationToScan = applicationToScan.getSuperclass(); } if (applicationPath != null) { if (StringUtils.isNotBlank(applicationPath.value())) { return applicationPath.value(); } } // look for inner application, e.g. ResourceConfig try { Application innerApp = application; Method m = application.getClass().getMethod("getApplication"); while (m != null) { Application retrievedApp = (Application) m.invoke(innerApp); if (retrievedApp == null) { break; } if (retrievedApp.getClass().equals(innerApp.getClass())) { break; } innerApp = retrievedApp; applicationPath = innerApp.getClass().getAnnotation(ApplicationPath.class); if (applicationPath != null) { if (StringUtils.isNotBlank(applicationPath.value())) { return applicationPath.value(); } } m = innerApp.getClass().getMethod("getApplication"); } } catch (Exception e) { // no inner application found } } return ""; } public OpenAPI read(Class cls, String parentPath, String parentMethod, boolean isSubresource, RequestBody parentRequestBody, ApiResponses parentResponses, Set parentTags, List parentParameters, Set> scannedResources) { Hidden hidden = cls.getAnnotation(Hidden.class); // class path final javax.ws.rs.Path apiPath = ReflectionUtils.getAnnotation(cls, javax.ws.rs.Path.class); final boolean openapi31 = Boolean.TRUE.equals(config.isOpenAPI31()); if ( openapi31 && ( config.getOpenAPI() == null || config.getOpenAPI().getOpenapi() == null || config.getOpenAPI().getOpenapi().startsWith("3.0") ) && config.getOpenAPIVersion() == null) { openAPI.setOpenapi("3.1.0"); } if (hidden != null) { // || (apiPath == null && !isSubresource)) { return openAPI; } io.swagger.v3.oas.annotations.responses.ApiResponse[] classResponses = ReflectionUtils.getRepeatableAnnotationsArray(cls, io.swagger.v3.oas.annotations.responses.ApiResponse.class); List apiSecurityScheme = ReflectionUtils.getRepeatableAnnotations(cls, io.swagger.v3.oas.annotations.security.SecurityScheme.class); List apiSecurityRequirements = ReflectionUtils.getRepeatableAnnotations(cls, io.swagger.v3.oas.annotations.security.SecurityRequirement.class); io.swagger.v3.oas.annotations.Webhooks webhooksAnnotation = ReflectionUtils.getAnnotation(cls, io.swagger.v3.oas.annotations.Webhooks.class); ExternalDocumentation apiExternalDocs = ReflectionUtils.getAnnotation(cls, ExternalDocumentation.class); io.swagger.v3.oas.annotations.tags.Tag[] apiTags = ReflectionUtils.getRepeatableAnnotationsArray(cls, io.swagger.v3.oas.annotations.tags.Tag.class); io.swagger.v3.oas.annotations.servers.Server[] apiServers = ReflectionUtils.getRepeatableAnnotationsArray(cls, io.swagger.v3.oas.annotations.servers.Server.class); javax.ws.rs.Consumes classConsumes = ReflectionUtils.getAnnotation(cls, javax.ws.rs.Consumes.class); javax.ws.rs.Produces classProduces = ReflectionUtils.getAnnotation(cls, javax.ws.rs.Produces.class); boolean classDeprecated = ReflectionUtils.getAnnotation(cls, Deprecated.class) != null || (KotlinDetector.isKotlinPresent() && ReflectionUtils.getAnnotation(cls, KotlinDetector.getKotlinDeprecated()) != null); // OpenApiDefinition OpenAPIDefinition openAPIDefinition = ReflectionUtils.getAnnotation(cls, OpenAPIDefinition.class); if (openAPIDefinition != null) { // info AnnotationsUtils.getInfo(openAPIDefinition.info()).ifPresent(info -> openAPI.setInfo(info)); // OpenApiDefinition security requirements SecurityParser .getSecurityRequirements(openAPIDefinition.security()) .ifPresent(s -> openAPI.setSecurity(s)); // // OpenApiDefinition external docs AnnotationsUtils .getExternalDocumentation(openAPIDefinition.externalDocs()) .ifPresent(docs -> openAPI.setExternalDocs(docs)); // OpenApiDefinition tags AnnotationsUtils .getTags(openAPIDefinition.tags(), false) .ifPresent(tags -> openApiTags.addAll(tags)); // OpenApiDefinition servers AnnotationsUtils.getServers(openAPIDefinition.servers()).ifPresent(servers -> openAPI.setServers(servers)); // OpenApiDefinition extensions if (openAPIDefinition.extensions().length > 0) { openAPI.setExtensions(AnnotationsUtils .getExtensions(openapi31, openAPIDefinition.extensions())); } } // class security schemes if (apiSecurityScheme != null) { for (io.swagger.v3.oas.annotations.security.SecurityScheme securitySchemeAnnotation : apiSecurityScheme) { Optional securityScheme = SecurityParser.getSecurityScheme(securitySchemeAnnotation); if (securityScheme.isPresent()) { Map securitySchemeMap = new HashMap<>(); if (StringUtils.isNotBlank(securityScheme.get().key)) { securitySchemeMap.put(securityScheme.get().key, securityScheme.get().securityScheme); if (components.getSecuritySchemes() != null && !components.getSecuritySchemes().isEmpty()) { components.getSecuritySchemes().putAll(securitySchemeMap); } else { components.setSecuritySchemes(securitySchemeMap); } } } } } // class security requirements List classSecurityRequirements = new ArrayList<>(); if (apiSecurityRequirements != null) { Optional> requirementsObject = SecurityParser.getSecurityRequirements( apiSecurityRequirements.toArray(new io.swagger.v3.oas.annotations.security.SecurityRequirement[apiSecurityRequirements.size()]) ); if (requirementsObject.isPresent()) { classSecurityRequirements = requirementsObject.get(); } } // class tags, consider only name to add to class operations final Set classTags = new LinkedHashSet<>(); if (apiTags != null) { AnnotationsUtils .getTags(apiTags, false).ifPresent(tags -> tags .stream() .map(Tag::getName) .forEach(classTags::add) ); } // parent tags if (isSubresource) { if (parentTags != null) { classTags.addAll(parentTags); } } // servers final List classServers = new ArrayList<>(); if (apiServers != null) { AnnotationsUtils.getServers(apiServers).ifPresent(classServers::addAll); } // class external docs Optional classExternalDocumentation = AnnotationsUtils.getExternalDocumentation(apiExternalDocs); JavaType classType = TypeFactory.defaultInstance().constructType(cls); BeanDescription bd; if (openapi31) { bd = Json31.mapper().getSerializationConfig().introspect(classType); } else { bd = Json.mapper().getSerializationConfig().introspect(classType); } final List globalParameters = new ArrayList<>(); // look for constructor-level annotated properties globalParameters.addAll(ReaderUtils.collectConstructorParameters(cls, components, classConsumes, null, config.getSchemaResolution(), openapi31)); // look for field-level annotated properties globalParameters.addAll(ReaderUtils.collectFieldParameters(cls, components, classConsumes, null)); // Make sure that the class methods are sorted for deterministic order // See https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getMethods-- final List methods = Arrays.stream(cls.getMethods()) .sorted(new MethodComparator()) .collect(Collectors.toList()); // iterate class methods for (Method method : methods) { if (isOperationHidden(method)) { continue; } AnnotatedMethod annotatedMethod = bd.findMethod(method.getName(), method.getParameterTypes()); javax.ws.rs.Produces methodProduces = ReflectionUtils.getAnnotation(method, javax.ws.rs.Produces.class); javax.ws.rs.Consumes methodConsumes = ReflectionUtils.getAnnotation(method, javax.ws.rs.Consumes.class); if (isMethodOverridden(method, cls)) { continue; } boolean methodDeprecated = ReflectionUtils.getAnnotation(method, Deprecated.class) != null || (KotlinDetector.isKotlinPresent() && ReflectionUtils.getAnnotation(method, KotlinDetector.getKotlinDeprecated()) != null); javax.ws.rs.Path methodPath = ReflectionUtils.getAnnotation(method, javax.ws.rs.Path.class); String operationPath = ReaderUtils.getPath(apiPath, methodPath, parentPath, isSubresource); // skip if path is the same as parent, e.g. for @ApplicationPath annotated application // extending resource config. if (ignoreOperationPath(operationPath, parentPath) && !isSubresource) { continue; } Map regexMap = new LinkedHashMap<>(); operationPath = PathUtils.parsePath(operationPath, regexMap); if (operationPath != null) { if (config != null && ReaderUtils.isIgnored(operationPath, config)) { continue; } final Class subResource = getSubResourceWithJaxRsSubresourceLocatorSpecs(method); String httpMethod = ReaderUtils.extractOperationMethod(method, OpenAPIExtensions.chain()); httpMethod = (httpMethod == null && isSubresource) ? parentMethod : httpMethod; if (StringUtils.isBlank(httpMethod) && subResource == null) { continue; } else if (StringUtils.isBlank(httpMethod) && subResource != null) { Type returnType = method.getGenericReturnType(); if (annotatedMethod != null && annotatedMethod.getType() != null) { returnType = annotatedMethod.getType(); } if (shouldIgnoreClass(returnType.getTypeName()) && !method.getGenericReturnType().equals(subResource)) { continue; } } io.swagger.v3.oas.annotations.Operation apiOperation = ReflectionUtils.getAnnotation(method, io.swagger.v3.oas.annotations.Operation.class); JsonView jsonViewAnnotation; JsonView jsonViewAnnotationForRequestBody; if (apiOperation != null && apiOperation.ignoreJsonView()) { jsonViewAnnotation = null; jsonViewAnnotationForRequestBody = null; } else { jsonViewAnnotation = ReflectionUtils.getAnnotation(method, JsonView.class); /* If one and only one exists, use the @JsonView annotation from the method parameter annotated with @RequestBody. Otherwise fall back to the @JsonView annotation for the method itself. */ jsonViewAnnotationForRequestBody = (JsonView) Arrays.stream(ReflectionUtils.getParameterAnnotations(method)) .filter(arr -> Arrays.stream(arr) .anyMatch(annotation -> annotation.annotationType() .equals(io.swagger.v3.oas.annotations.parameters.RequestBody.class) ) ).flatMap(Arrays::stream) .filter(annotation -> annotation.annotationType() .equals(JsonView.class) ).reduce((a, b) -> null) .orElse(jsonViewAnnotation); } Operation operation = parseMethod( method, globalParameters, methodProduces, classProduces, methodConsumes, classConsumes, classSecurityRequirements, classExternalDocumentation, classTags, classServers, isSubresource, parentRequestBody, parentResponses, jsonViewAnnotation, classResponses, annotatedMethod); if (operation != null) { if (classDeprecated || methodDeprecated) { operation.setDeprecated(true); } List operationParameters = new ArrayList<>(); List formParameters = new ArrayList<>(); Annotation[][] paramAnnotations = ReflectionUtils.getParameterAnnotations(method); if (annotatedMethod == null) { // annotatedMethod not null only when method with 0-2 parameters Type[] genericParameterTypes = method.getGenericParameterTypes(); for (int i = 0; i < genericParameterTypes.length; i++) { final Type type = TypeFactory.defaultInstance().constructType(genericParameterTypes[i], cls); io.swagger.v3.oas.annotations.Parameter paramAnnotation = AnnotationsUtils.getAnnotation(io.swagger.v3.oas.annotations.Parameter.class, paramAnnotations[i]); Type paramType = ParameterProcessor.getParameterType(paramAnnotation, true); if (paramType == null) { paramType = type; } else { if (!(paramType instanceof Class)) { paramType = type; } } ResolvedParameter resolvedParameter = getParameters(paramType, Arrays.asList(paramAnnotations[i]), operation, classConsumes, methodConsumes, jsonViewAnnotation); operationParameters.addAll(resolvedParameter.parameters); // collect params to use together as request Body formParameters.addAll(resolvedParameter.formParameters); if (resolvedParameter.requestBody != null) { processRequestBody( resolvedParameter.requestBody, operation, methodConsumes, classConsumes, operationParameters, paramAnnotations[i], type, jsonViewAnnotationForRequestBody, null); } } } else { for (int i = 0; i < annotatedMethod.getParameterCount(); i++) { AnnotatedParameter param = annotatedMethod.getParameter(i); final Type type = TypeFactory.defaultInstance().constructType(param.getParameterType(), cls); io.swagger.v3.oas.annotations.Parameter paramAnnotation = AnnotationsUtils.getAnnotation(io.swagger.v3.oas.annotations.Parameter.class, paramAnnotations[i]); Type paramType = ParameterProcessor.getParameterType(paramAnnotation, true); if (paramType == null) { paramType = type; } else { if (!(paramType instanceof Class)) { paramType = type; } } ResolvedParameter resolvedParameter = getParameters(paramType, Arrays.asList(paramAnnotations[i]), operation, classConsumes, methodConsumes, jsonViewAnnotation); operationParameters.addAll(resolvedParameter.parameters); // collect params to use together as request Body formParameters.addAll(resolvedParameter.formParameters); if (resolvedParameter.requestBody != null) { processRequestBody( resolvedParameter.requestBody, operation, methodConsumes, classConsumes, operationParameters, paramAnnotations[i], type, jsonViewAnnotationForRequestBody, null); } } } // if we have form parameters, need to merge them into single schema and use as request body.. if (!formParameters.isEmpty()) { Schema mergedSchema = new ObjectSchema(); Map encoding = new LinkedHashMap<>(); for (Parameter formParam: formParameters) { if (formParam.getExplode() != null || (formParam.getStyle() != null) && Encoding.StyleEnum.fromString(formParam.getStyle().toString()) != null) { Encoding e = new Encoding(); if (formParam.getExplode() != null) { e.explode(formParam.getExplode()); } if (formParam.getStyle() != null && Encoding.StyleEnum.fromString(formParam.getStyle().toString()) != null) { e.style(Encoding.StyleEnum.fromString(formParam.getStyle().toString())); } encoding.put(formParam.getName(), e); } mergedSchema.addProperty(formParam.getName(), formParam.getSchema()); if (formParam.getSchema() != null && StringUtils.isNotBlank(formParam.getDescription()) && StringUtils.isBlank(formParam.getSchema().getDescription())) { formParam.getSchema().description(formParam.getDescription()); } if (null != formParam.getRequired() && formParam.getRequired()) { mergedSchema.addRequiredItem(formParam.getName()); } } Parameter merged = new Parameter().schema(mergedSchema); processRequestBody( merged, operation, methodConsumes, classConsumes, operationParameters, new Annotation[0], null, jsonViewAnnotationForRequestBody, encoding); } if (!operationParameters.isEmpty()) { for (Parameter operationParameter : operationParameters) { operation.addParametersItem(operationParameter); } } // if subresource, merge parent parameters if (parentParameters != null) { for (Parameter parentParameter : parentParameters) { operation.addParametersItem(parentParameter); } } if (subResource != null && !scannedResources.contains(subResource)) { scannedResources.add(subResource); read(subResource, operationPath, httpMethod, true, operation.getRequestBody(), operation.getResponses(), classTags, operation.getParameters(), scannedResources); // remove the sub resource so that it can visit it later in another path // but we have a room for optimization in the future to reuse the scanned result // by caching the scanned resources in the reader instance to avoid actual scanning // the the resources again scannedResources.remove(subResource); // don't proceed with root resource operation, as it's handled by subresource continue; } final Iterator chain = OpenAPIExtensions.chain(); if (chain.hasNext()) { final OpenAPIExtension extension = chain.next(); extension.decorateOperation(operation, method, chain); } PathItem pathItemObject; if (openAPI.getPaths() != null && openAPI.getPaths().get(operationPath) != null) { pathItemObject = openAPI.getPaths().get(operationPath); } else { pathItemObject = new PathItem(); } if (StringUtils.isBlank(httpMethod)) { continue; } setPathItemOperation(pathItemObject, httpMethod, operation); applyPathParamsPatterns(operation, regexMap); paths.addPathItem(operationPath, pathItemObject); if (openAPI.getPaths() != null) { this.paths.putAll(openAPI.getPaths()); } openAPI.setPaths(this.paths); } } } if (webhooksAnnotation != null && webhooksAnnotation.value().length > 0) { Map webhooks = new HashMap<>(); for (io.swagger.v3.oas.annotations.Webhook webhookAnnotation : webhooksAnnotation.value()) { io.swagger.v3.oas.annotations.Operation apiOperation = webhookAnnotation.operation(); PathItem pathItemObject = new PathItem(); Operation operation = new Operation(); setOperationObjectFromApiOperationAnnotation(operation, apiOperation, null, classProduces, null, classConsumes, null); pathItemObject.post(operation); webhooks.put(webhookAnnotation.name(), pathItemObject); } if (!webhooks.isEmpty()) { openAPI.setWebhooks(webhooks); } } // if no components object is defined in openApi instance passed by client, set openAPI.components to resolved components (if not empty) if (!isEmptyComponents(components) && openAPI.getComponents() == null) { openAPI.setComponents(components); } // add tags from class to definition tags AnnotationsUtils .getTags(apiTags, true).ifPresent(tags -> openApiTags.addAll(tags)); if (!openApiTags.isEmpty()) { Set tagsSet = new LinkedHashSet<>(); if (openAPI.getTags() != null) { for (Tag tag : openAPI.getTags()) { if (tagsSet.stream().noneMatch(t -> t.getName().equals(tag.getName()))) { tagsSet.add(tag); } } } for (Tag tag : openApiTags) { if (tagsSet.stream().noneMatch(t -> t.getName().equals(tag.getName()))) { tagsSet.add(tag); } } openAPI.setTags(new ArrayList<>(tagsSet)); } return openAPI; } protected void applyPathParamsPatterns(Operation operation, Map patternsMap) { if (operation.getParameters() == null) { return; } operation.getParameters().stream() .filter(p -> patternsMap.containsKey(p.getName())) .filter(p -> "path".equals(p.getIn())) .filter(p -> p.getSchema() != null) .filter(p -> StringUtils.isBlank(p.getSchema().getPattern())) .filter(p -> !Parameter.StyleEnum.MATRIX.equals(p.getStyle())) .filter(p -> "string".equals(p.getSchema().getType()) || (p.getSchema().getTypes() != null && p.getSchema().getTypes().contains("string"))) .forEach(p -> p.getSchema().setPattern(patternsMap.get(p.getName()))); } protected Content processContent(Content content, Schema schema, Consumes methodConsumes, Consumes classConsumes) { if (content == null) { content = new Content(); } if (methodConsumes != null) { for (String value : methodConsumes.value()) { setMediaTypeToContent(schema, content, value); } } else if (classConsumes != null) { for (String value : classConsumes.value()) { setMediaTypeToContent(schema, content, value); } } else { setMediaTypeToContent(schema, content, DEFAULT_MEDIA_TYPE_VALUE); } return content; } protected void processRequestBody(Parameter requestBodyParameter, Operation operation, Consumes methodConsumes, Consumes classConsumes, List operationParameters, Annotation[] paramAnnotations, Type type, JsonView jsonViewAnnotation, Map encoding) { io.swagger.v3.oas.annotations.parameters.RequestBody requestBodyAnnotation = getRequestBody(Arrays.asList(paramAnnotations)); if (requestBodyAnnotation != null) { Optional optionalRequestBody = OperationParser.getRequestBody(requestBodyAnnotation, classConsumes, methodConsumes, components, jsonViewAnnotation, config.isOpenAPI31()); if (optionalRequestBody.isPresent()) { RequestBody requestBody = optionalRequestBody.get(); if (StringUtils.isBlank(requestBody.get$ref()) && (requestBody.getContent() == null || requestBody.getContent().isEmpty())) { if (requestBodyParameter.getSchema() != null) { Content content = processContent(requestBody.getContent(), requestBodyParameter.getSchema(), methodConsumes, classConsumes); requestBody.setContent(content); } } else if (StringUtils.isBlank(requestBody.get$ref()) && requestBody.getContent() != null && !requestBody.getContent().isEmpty()) { if (requestBodyParameter.getSchema() != null) { Map reresolvedMediaTypes = new LinkedHashMap<>(); for (String key: requestBody.getContent().keySet()) { MediaType mediaType = requestBody.getContent().get(key); if (mediaType.getSchema() == null) { if (requestBodyParameter.getSchema() == null) { mediaType.setSchema(new Schema()); } else { mediaType.setSchema(requestBodyParameter.getSchema()); } } else if (mediaType.getSchema() != null && requestBodyAnnotation.useParameterTypeSchema()) { if (requestBodyParameter.getSchema() != null) { MediaType newMediaType = clone(mediaType); Schema parameterSchema = clone(requestBodyParameter.getSchema()); Optional content = Arrays.stream(requestBodyAnnotation.content()).filter(c -> c.mediaType().equals(key)).findFirst(); if (content.isPresent()) { Optional reResolvedSchema = AnnotationsUtils.getSchemaFromAnnotation(content.get().schema(), components, null, config.isOpenAPI31(), parameterSchema); if (reResolvedSchema.isPresent()) { parameterSchema = reResolvedSchema.get(); } reResolvedSchema = AnnotationsUtils.getArraySchema(content.get().array(), components, null, config.isOpenAPI31(), parameterSchema); if (reResolvedSchema.isPresent()) { parameterSchema = reResolvedSchema.get(); } } newMediaType.schema(parameterSchema); reresolvedMediaTypes.put(key, newMediaType); } } if (StringUtils.isBlank(mediaType.getSchema().getType()) || requestBodyAnnotation.useParameterTypeSchema()) { mediaType.getSchema().setType(requestBodyParameter.getSchema().getType()); } } requestBody.getContent().putAll(reresolvedMediaTypes); } } operation.setRequestBody(requestBody); } } else { if (operation.getRequestBody() == null) { boolean isRequestBodyEmpty = true; RequestBody requestBody = new RequestBody(); if (StringUtils.isNotBlank(requestBodyParameter.get$ref())) { requestBody.set$ref(requestBodyParameter.get$ref()); isRequestBodyEmpty = false; } if (StringUtils.isNotBlank(requestBodyParameter.getDescription())) { requestBody.setDescription(requestBodyParameter.getDescription()); isRequestBodyEmpty = false; } if (Boolean.TRUE.equals(requestBodyParameter.getRequired())) { requestBody.setRequired(requestBodyParameter.getRequired()); isRequestBodyEmpty = false; } if (requestBodyParameter.getSchema() != null) { Content content = processContent(null, requestBodyParameter.getSchema(), methodConsumes, classConsumes); requestBody.setContent(content); isRequestBodyEmpty = false; } if (!isRequestBodyEmpty) { operation.setRequestBody(requestBody); } } } if (operation.getRequestBody() != null && operation.getRequestBody().getContent() != null && encoding != null && !encoding.isEmpty()) { Content content = operation.getRequestBody().getContent(); for (String mediaKey: content.keySet()) { if (mediaKey.equals(javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED) || mediaKey.equals(javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA)) { MediaType m = content.get(mediaKey); m.encoding(encoding); } } } } private io.swagger.v3.oas.annotations.parameters.RequestBody getRequestBody(List annotations) { if (annotations == null) { return null; } for (Annotation a : annotations) { if (a instanceof io.swagger.v3.oas.annotations.parameters.RequestBody) { return (io.swagger.v3.oas.annotations.parameters.RequestBody) a; } } return null; } private void setMediaTypeToContent(Schema schema, Content content, String value) { MediaType mediaTypeObject = new MediaType(); mediaTypeObject.setSchema(schema); content.addMediaType(value, mediaTypeObject); } public Operation parseMethod( Method method, List globalParameters, JsonView jsonViewAnnotation) { JavaType classType = TypeFactory.defaultInstance().constructType(method.getDeclaringClass()); return parseMethod( classType.getClass(), method, globalParameters, null, null, null, null, new ArrayList<>(), Optional.empty(), new HashSet<>(), new ArrayList<>(), false, null, null, jsonViewAnnotation, null, null); } public Operation parseMethod( Method method, List globalParameters, Produces methodProduces, Produces classProduces, Consumes methodConsumes, Consumes classConsumes, List classSecurityRequirements, Optional classExternalDocs, Set classTags, List classServers, boolean isSubresource, RequestBody parentRequestBody, ApiResponses parentResponses, JsonView jsonViewAnnotation, io.swagger.v3.oas.annotations.responses.ApiResponse[] classResponses) { JavaType classType = TypeFactory.defaultInstance().constructType(method.getDeclaringClass()); return parseMethod( classType.getClass(), method, globalParameters, methodProduces, classProduces, methodConsumes, classConsumes, classSecurityRequirements, classExternalDocs, classTags, classServers, isSubresource, parentRequestBody, parentResponses, jsonViewAnnotation, classResponses, null); } public Operation parseMethod( Method method, List globalParameters, Produces methodProduces, Produces classProduces, Consumes methodConsumes, Consumes classConsumes, List classSecurityRequirements, Optional classExternalDocs, Set classTags, List classServers, boolean isSubresource, RequestBody parentRequestBody, ApiResponses parentResponses, JsonView jsonViewAnnotation, io.swagger.v3.oas.annotations.responses.ApiResponse[] classResponses, AnnotatedMethod annotatedMethod) { JavaType classType = TypeFactory.defaultInstance().constructType(method.getDeclaringClass()); return parseMethod( classType.getClass(), method, globalParameters, methodProduces, classProduces, methodConsumes, classConsumes, classSecurityRequirements, classExternalDocs, classTags, classServers, isSubresource, parentRequestBody, parentResponses, jsonViewAnnotation, classResponses, annotatedMethod); } protected Operation parseMethod( Class cls, Method method, List globalParameters, Produces methodProduces, Produces classProduces, Consumes methodConsumes, Consumes classConsumes, List classSecurityRequirements, Optional classExternalDocs, Set classTags, List classServers, boolean isSubresource, RequestBody parentRequestBody, ApiResponses parentResponses, JsonView jsonViewAnnotation, io.swagger.v3.oas.annotations.responses.ApiResponse[] classResponses, AnnotatedMethod annotatedMethod) { Operation operation = new Operation(); io.swagger.v3.oas.annotations.Operation apiOperation = ReflectionUtils.getAnnotation(method, io.swagger.v3.oas.annotations.Operation.class); List apiSecurity = ReflectionUtils.getRepeatableAnnotations(method, io.swagger.v3.oas.annotations.security.SecurityRequirement.class); List apiCallbacks = ReflectionUtils.getRepeatableAnnotations(method, io.swagger.v3.oas.annotations.callbacks.Callback.class); List apiServers = ReflectionUtils.getRepeatableAnnotations(method, Server.class); List apiTags = ReflectionUtils.getRepeatableAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class); List apiParameters = ReflectionUtils.getRepeatableAnnotations(method, io.swagger.v3.oas.annotations.Parameter.class); List apiResponses = ReflectionUtils.getRepeatableAnnotations(method, io.swagger.v3.oas.annotations.responses.ApiResponse.class); io.swagger.v3.oas.annotations.parameters.RequestBody apiRequestBody = ReflectionUtils.getAnnotation(method, io.swagger.v3.oas.annotations.parameters.RequestBody.class); io.swagger.v3.oas.annotations.responses.ApiResponse[] operationApiResponses = new io.swagger.v3.oas.annotations.responses.ApiResponse[] {}; if (apiOperation != null) { operationApiResponses = apiOperation.responses(); } ExternalDocumentation apiExternalDocumentation = ReflectionUtils.getAnnotation(method, ExternalDocumentation.class); // callbacks Map callbacks = new LinkedHashMap<>(); if (apiCallbacks != null) { for (io.swagger.v3.oas.annotations.callbacks.Callback methodCallback : apiCallbacks) { Map currentCallbacks = getCallbacks(methodCallback, methodProduces, classProduces, methodConsumes, classConsumes, jsonViewAnnotation); callbacks.putAll(currentCallbacks); } } if (!callbacks.isEmpty()) { operation.setCallbacks(callbacks); } // security classSecurityRequirements.forEach(operation::addSecurityItem); if (apiSecurity != null) { Optional> requirementsObject = SecurityParser.getSecurityRequirements(apiSecurity.toArray(new io.swagger.v3.oas.annotations.security.SecurityRequirement[apiSecurity.size()])); if (requirementsObject.isPresent()) { requirementsObject.get().stream() .filter(r -> operation.getSecurity() == null || !operation.getSecurity().contains(r)) .forEach(operation::addSecurityItem); } } // servers if (classServers != null) { classServers.forEach(operation::addServersItem); } if (apiServers != null) { AnnotationsUtils.getServers(apiServers.toArray(new Server[apiServers.size()])).ifPresent(servers -> servers.forEach(operation::addServersItem)); } // external docs AnnotationsUtils.getExternalDocumentation(apiExternalDocumentation).ifPresent(operation::setExternalDocs); // method tags if (apiTags != null) { apiTags.stream() .filter(t -> operation.getTags() == null || (operation.getTags() != null && !operation.getTags().contains(t.name()))) .map(io.swagger.v3.oas.annotations.tags.Tag::name) .forEach(operation::addTagsItem); AnnotationsUtils.getTags(apiTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[apiTags.size()]), true).ifPresent(tags -> openApiTags.addAll(tags)); } // parameters if (globalParameters != null) { for (Parameter globalParameter : globalParameters) { operation.addParametersItem(globalParameter); } } if (apiParameters != null) { getParametersListFromAnnotation( apiParameters.toArray(new io.swagger.v3.oas.annotations.Parameter[apiParameters.size()]), classConsumes, methodConsumes, operation, jsonViewAnnotation).ifPresent(p -> p.forEach(operation::addParametersItem)); } // RequestBody in Method if (apiRequestBody != null && operation.getRequestBody() == null){ OperationParser.getRequestBody(apiRequestBody, classConsumes, methodConsumes, components, jsonViewAnnotation, config.isOpenAPI31()).ifPresent( operation::setRequestBody); } // operation id if (StringUtils.isBlank(operation.getOperationId())) { operation.setOperationId(getOperationId(method.getName())); } // classResponses if (classResponses != null && classResponses.length > 0) { OperationParser.getApiResponses( classResponses, classProduces, methodProduces, components, jsonViewAnnotation, config.isOpenAPI31(), defaultResponseKey ).ifPresent(responses -> { if (operation.getResponses() == null) { operation.setResponses(responses); } else { responses.forEach(operation.getResponses()::addApiResponse); } }); } if (apiOperation != null) { setOperationObjectFromApiOperationAnnotation(operation, apiOperation, methodProduces, classProduces, methodConsumes, classConsumes, jsonViewAnnotation); } // apiResponses if (apiResponses != null && !apiResponses.isEmpty()) { OperationParser.getApiResponses( apiResponses.toArray(new io.swagger.v3.oas.annotations.responses.ApiResponse[apiResponses.size()]), classProduces, methodProduces, components, jsonViewAnnotation, config.isOpenAPI31(), defaultResponseKey ).ifPresent(responses -> { if (operation.getResponses() == null) { operation.setResponses(responses); } else { responses.forEach(operation.getResponses()::addApiResponse); } }); } // class tags after tags defined as field of @Operation if (classTags != null) { classTags.stream() .filter(t -> operation.getTags() == null || (operation.getTags() != null && !operation.getTags().contains(t))) .forEach(operation::addTagsItem); } // external docs of class if not defined in annotation of method or as field of Operation annotation if (operation.getExternalDocs() == null) { classExternalDocs.ifPresent(operation::setExternalDocs); } // if subresource, merge parent requestBody if (isSubresource && parentRequestBody != null) { if (operation.getRequestBody() == null) { operation.requestBody(parentRequestBody); } else { Content content = operation.getRequestBody().getContent(); if (content == null) { content = parentRequestBody.getContent(); operation.getRequestBody().setContent(content); } else if (parentRequestBody.getContent() != null){ for (String parentMediaType: parentRequestBody.getContent().keySet()) { if (content.get(parentMediaType) == null) { content.addMediaType(parentMediaType, parentRequestBody.getContent().get(parentMediaType)); } } } } } // handle return type, add as response in case. Type returnType = method.getGenericReturnType(); if (annotatedMethod != null && annotatedMethod.getType() != null) { returnType = extractTypeFromMethod(annotatedMethod); } final Class subResource = getSubResourceWithJaxRsSubresourceLocatorSpecs(method); Schema returnTypeSchema = null; if (!shouldIgnoreClass(returnType.getTypeName()) && !method.getGenericReturnType().equals(subResource)) { ResolvedSchema resolvedSchema = ModelConverters.getInstance(config.toConfiguration()).resolveAsResolvedSchema(new AnnotatedType(returnType).resolveAsRef(true).jsonViewAnnotation(jsonViewAnnotation).components(components)); if (resolvedSchema.schema != null) { returnTypeSchema = resolvedSchema.schema; Content content = new Content(); MediaType mediaType = new MediaType().schema(returnTypeSchema); AnnotationsUtils.applyTypes(classProduces == null ? new String[0] : classProduces.value(), methodProduces == null ? new String[0] : methodProduces.value(), content, mediaType); if (operation.getResponses() == null) { operation.responses( new ApiResponses().addApiResponse(defaultResponseKey, new ApiResponse().description(DEFAULT_DESCRIPTION) .content(content) ) ); } if (operation.getResponses().get(defaultResponseKey) != null && StringUtils.isBlank(operation.getResponses().get(defaultResponseKey).get$ref())) { if (operation.getResponses().get(defaultResponseKey).getContent() == null) { operation.getResponses().get(defaultResponseKey).content(content); } else { for (String key : operation.getResponses().get(defaultResponseKey).getContent().keySet()) { if (operation.getResponses().get(defaultResponseKey).getContent().get(key).getSchema() == null) { operation.getResponses().get(defaultResponseKey).getContent().get(key).setSchema(returnTypeSchema); } } } } Map schemaMap = resolvedSchema.referencedSchemas; if (schemaMap != null) { schemaMap.forEach((key, schema) -> components.addSchemas(key, schema)); } } } if (operation.getResponses() == null || operation.getResponses().isEmpty()) { Content content = resolveEmptyContent(classProduces, methodProduces); ApiResponse apiResponseObject = new ApiResponse().description(DEFAULT_DESCRIPTION).content(content); operation.setResponses(new ApiResponses().addApiResponse(defaultResponseKey, apiResponseObject)); } if (returnTypeSchema != null) { resolveResponseSchemaFromReturnType(operation, classResponses, returnTypeSchema, classProduces, methodProduces); if (apiResponses != null) { resolveResponseSchemaFromReturnType( operation, apiResponses.toArray( new io.swagger.v3.oas.annotations.responses.ApiResponse[0]), returnTypeSchema, classProduces, methodProduces); } else if (operationApiResponses != null && operationApiResponses.length > 0) { resolveResponseSchemaFromReturnType( operation, operationApiResponses, returnTypeSchema, classProduces, methodProduces); } } return operation; } private Type extractTypeFromMethod(AnnotatedMethod annotatedMethod) { if(CompletionStage.class.isAssignableFrom(annotatedMethod.getType().getRawClass())) { // CompletionStage's 1st generic type is the real return type. return annotatedMethod.getType().getBindings().getBoundType(0); } return annotatedMethod.getType(); } protected Content resolveEmptyContent(Produces classProduces, Produces methodProduces) { Content content = new Content(); MediaType mediaType = new MediaType(); AnnotationsUtils.applyTypes(classProduces == null ? new String[0] : classProduces.value(), methodProduces == null ? new String[0] : methodProduces.value(), content, mediaType); return content; } private MediaType clone(MediaType mediaType) { if(mediaType == null) return mediaType; try { if(config.isOpenAPI31()) { mediaType = Json31.mapper().readValue(Json31.pretty(mediaType), MediaType.class); } else { mediaType = Json.mapper().readValue(Json.pretty(mediaType), MediaType.class); } } catch (IOException e) { LOGGER.error("Could not clone mediaType", e); } return mediaType; } private Schema clone(Schema schema) { return AnnotationsUtils.clone(schema, config.isOpenAPI31()); } protected void resolveResponseSchemaFromReturnType( Operation operation, io.swagger.v3.oas.annotations.responses.ApiResponse[] responses, Schema schema, Produces classProduces, Produces methodProduces) { if (responses != null) { for (io.swagger.v3.oas.annotations.responses.ApiResponse response: responses) { Map reresolvedMediaTypes = new LinkedHashMap<>(); if (response.useReturnTypeSchema()) { ApiResponse opResponse = operation.getResponses().get(response.responseCode()); if (opResponse != null) { if (opResponse.getContent() != null) { for (String key : opResponse.getContent().keySet()) { MediaType mediaType = clone(opResponse.getContent().get(key)); Schema existingSchema = clone(schema); Optional content = Arrays.stream(response.content()).filter(c -> c.mediaType().equals(key)).findFirst(); if (content.isPresent()) { Optional reResolvedSchema = AnnotationsUtils.getSchemaFromAnnotation(content.get().schema(), components, null, config.isOpenAPI31(), existingSchema); if (reResolvedSchema.isPresent()) { existingSchema = reResolvedSchema.get(); } reResolvedSchema = AnnotationsUtils.getArraySchema(content.get().array(), components, null, config.isOpenAPI31(), existingSchema); if (reResolvedSchema.isPresent()) { existingSchema = reResolvedSchema.get(); } } mediaType.schema(existingSchema); reresolvedMediaTypes.put(key, mediaType); } } else { Content content = resolveEmptyContent(classProduces, methodProduces); for (MediaType mediaType : content.values()) { mediaType.schema(schema); } opResponse.content(content); } opResponse.getContent().putAll(reresolvedMediaTypes); } } } } } private boolean shouldIgnoreClass(String className) { if (StringUtils.isBlank(className)) { return true; } boolean ignore = false; String rawClassName = className; if (rawClassName.startsWith("[")) { // jackson JavaType rawClassName = className.replace("[simple type, class ", ""); rawClassName = rawClassName.substring(0, rawClassName.length() -1); } ignore = rawClassName.startsWith("javax.ws.rs."); ignore = ignore || rawClassName.equalsIgnoreCase("void"); ignore = ignore || ModelConverters.getInstance(config.toConfiguration()).isRegisteredAsSkippedClass(rawClassName); return ignore; } private Map getCallbacks( io.swagger.v3.oas.annotations.callbacks.Callback apiCallback, Produces methodProduces, Produces classProduces, Consumes methodConsumes, Consumes classConsumes, JsonView jsonViewAnnotation) { Map callbackMap = new HashMap<>(); if (apiCallback == null) { return callbackMap; } Callback callbackObject = new Callback(); if (StringUtils.isNotBlank(apiCallback.ref())) { callbackObject.set$ref(apiCallback.ref()); callbackMap.put(apiCallback.name(), callbackObject); return callbackMap; } PathItem pathItemObject = new PathItem(); for (io.swagger.v3.oas.annotations.Operation callbackOperation : apiCallback.operation()) { Operation callbackNewOperation = new Operation(); setOperationObjectFromApiOperationAnnotation( callbackNewOperation, callbackOperation, methodProduces, classProduces, methodConsumes, classConsumes, jsonViewAnnotation); setPathItemOperation(pathItemObject, callbackOperation.method(), callbackNewOperation); } callbackObject.addPathItem(apiCallback.callbackUrlExpression(), pathItemObject); callbackMap.put(apiCallback.name(), callbackObject); return callbackMap; } private void setPathItemOperation(PathItem pathItemObject, String method, Operation operation) { switch (method) { case POST_METHOD: pathItemObject.post(operation); break; case GET_METHOD: pathItemObject.get(operation); break; case DELETE_METHOD: pathItemObject.delete(operation); break; case PUT_METHOD: pathItemObject.put(operation); break; case PATCH_METHOD: pathItemObject.patch(operation); break; case TRACE_METHOD: pathItemObject.trace(operation); break; case HEAD_METHOD: pathItemObject.head(operation); break; case OPTIONS_METHOD: pathItemObject.options(operation); break; default: // Do nothing here break; } } protected void setOperationObjectFromApiOperationAnnotation( Operation operation, io.swagger.v3.oas.annotations.Operation apiOperation, Produces methodProduces, Produces classProduces, Consumes methodConsumes, Consumes classConsumes, JsonView jsonViewAnnotation) { if (StringUtils.isNotBlank(apiOperation.summary())) { operation.setSummary(apiOperation.summary()); } if (StringUtils.isNotBlank(apiOperation.description())) { operation.setDescription(apiOperation.description()); } if (StringUtils.isNotBlank(apiOperation.operationId())) { operation.setOperationId(getOperationId(apiOperation.operationId())); } if (apiOperation.deprecated()) { operation.setDeprecated(apiOperation.deprecated()); } final boolean openapi31 = Boolean.TRUE.equals(config.isOpenAPI31()); ReaderUtils.getStringListFromStringArray(apiOperation.tags()).ifPresent(tags -> tags.stream() .filter(t -> operation.getTags() == null || (operation.getTags() != null && !operation.getTags().contains(t))) .forEach(operation::addTagsItem)); if (operation.getExternalDocs() == null) { // if not set in root annotation AnnotationsUtils.getExternalDocumentation(apiOperation.externalDocs(), openapi31).ifPresent(operation::setExternalDocs); } OperationParser.getApiResponses(apiOperation.responses(), classProduces, methodProduces, components, jsonViewAnnotation, openapi31, defaultResponseKey).ifPresent(responses -> { if (operation.getResponses() == null) { operation.setResponses(responses); } else { responses.forEach(operation.getResponses()::addApiResponse); } }); AnnotationsUtils.getServers(apiOperation.servers()).ifPresent(servers -> servers.forEach(operation::addServersItem)); getParametersListFromAnnotation( apiOperation.parameters(), classConsumes, methodConsumes, operation, jsonViewAnnotation).ifPresent(p -> p.forEach(operation::addParametersItem)); // security Optional> requirementsObject = SecurityParser.getSecurityRequirements(apiOperation.security()); if (requirementsObject.isPresent()) { requirementsObject.get().stream() .filter(r -> operation.getSecurity() == null || !operation.getSecurity().contains(r)) .forEach(operation::addSecurityItem); } // RequestBody in Operation if (apiOperation.requestBody() != null && operation.getRequestBody() == null) { OperationParser.getRequestBody(apiOperation.requestBody(), classConsumes, methodConsumes, components, jsonViewAnnotation, config.isOpenAPI31()).ifPresent( operation::setRequestBody); } // Extensions in Operation if (apiOperation.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(openapi31, apiOperation.extensions()); if (extensions != null) { if (openapi31) { extensions.forEach(operation::addExtension31); } else { extensions.forEach(operation::addExtension); } } } } protected String getOperationId(String operationId) { boolean operationIdUsed = existOperationId(operationId); String operationIdToFind = null; int counter = 0; while (operationIdUsed) { operationIdToFind = String.format("%s_%d", operationId, ++counter); operationIdUsed = existOperationId(operationIdToFind); } if (operationIdToFind != null) { operationId = operationIdToFind; } return operationId; } private boolean existOperationId(String operationId) { if (openAPI == null) { return false; } if (openAPI.getPaths() == null || openAPI.getPaths().isEmpty()) { return false; } for (PathItem path : openAPI.getPaths().values()) { Set pathOperationIds = extractOperationIdFromPathItem(path); if (pathOperationIds.contains(operationId)) { return true; } } return false; } protected Optional> getParametersListFromAnnotation(io.swagger.v3.oas.annotations.Parameter[] parameters, Consumes classConsumes, Consumes methodConsumes, Operation operation, JsonView jsonViewAnnotation) { if (parameters == null) { return Optional.empty(); } List parametersObject = new ArrayList<>(); for (io.swagger.v3.oas.annotations.Parameter parameter : parameters) { ResolvedParameter resolvedParameter = getParameters(ParameterProcessor.getParameterType(parameter), Collections.singletonList(parameter), operation, classConsumes, methodConsumes, jsonViewAnnotation); parametersObject.addAll(resolvedParameter.parameters); } if (parametersObject.isEmpty()) { return Optional.empty(); } return Optional.of(parametersObject); } protected ResolvedParameter getParameters(Type type, List annotations, Operation operation, javax.ws.rs.Consumes classConsumes, javax.ws.rs.Consumes methodConsumes, JsonView jsonViewAnnotation) { final Iterator chain = OpenAPIExtensions.chain(); if (!chain.hasNext()) { return new ResolvedParameter(); } LOGGER.debug("getParameters for {}", type); Set typesToSkip = new HashSet<>(); final OpenAPIExtension extension = chain.next(); LOGGER.debug("trying extension {}", extension); Schema.SchemaResolution curSchemaResolution = config.getSchemaResolution(); extension.setConfiguration(config.toConfiguration()); ResolvedParameter resolvedParameter = extension.extractParameters(annotations, type, typesToSkip, components, classConsumes, methodConsumes, true, jsonViewAnnotation, chain); ((SwaggerConfiguration)config).setSchemaResolution(curSchemaResolution); return resolvedParameter; } private Set extractOperationIdFromPathItem(PathItem path) { Set ids = new HashSet<>(); if (path.getGet() != null && StringUtils.isNotBlank(path.getGet().getOperationId())) { ids.add(path.getGet().getOperationId()); } if (path.getPost() != null && StringUtils.isNotBlank(path.getPost().getOperationId())) { ids.add(path.getPost().getOperationId()); } if (path.getPut() != null && StringUtils.isNotBlank(path.getPut().getOperationId())) { ids.add(path.getPut().getOperationId()); } if (path.getDelete() != null && StringUtils.isNotBlank(path.getDelete().getOperationId())) { ids.add(path.getDelete().getOperationId()); } if (path.getOptions() != null && StringUtils.isNotBlank(path.getOptions().getOperationId())) { ids.add(path.getOptions().getOperationId()); } if (path.getHead() != null && StringUtils.isNotBlank(path.getHead().getOperationId())) { ids.add(path.getHead().getOperationId()); } if (path.getPatch() != null && StringUtils.isNotBlank(path.getPatch().getOperationId())) { ids.add(path.getPatch().getOperationId()); } return ids; } private boolean isEmptyComponents(Components components) { if (components == null) { return true; } if (components.getSchemas() != null && !components.getSchemas().isEmpty()) { return false; } if (components.getSecuritySchemes() != null && !components.getSecuritySchemes().isEmpty()) { return false; } if (components.getCallbacks() != null && !components.getCallbacks().isEmpty()) { return false; } if (components.getExamples() != null && !components.getExamples().isEmpty()) { return false; } if (components.getExtensions() != null && !components.getExtensions().isEmpty()) { return false; } if (components.getHeaders() != null && !components.getHeaders().isEmpty()) { return false; } if (components.getLinks() != null && !components.getLinks().isEmpty()) { return false; } if (components.getParameters() != null && !components.getParameters().isEmpty()) { return false; } if (components.getRequestBodies() != null && !components.getRequestBodies().isEmpty()) { return false; } if (components.getResponses() != null && !components.getResponses().isEmpty()) { return false; } if (components.getPathItems() != null && !components.getPathItems().isEmpty()) { return false; } return true; } protected boolean isOperationHidden(Method method) { io.swagger.v3.oas.annotations.Operation apiOperation = ReflectionUtils.getAnnotation(method, io.swagger.v3.oas.annotations.Operation.class); if (apiOperation != null && apiOperation.hidden()) { return true; } Hidden hidden = method.getAnnotation(Hidden.class); if (hidden != null) { return true; } if (config != null && !Boolean.TRUE.equals(config.isReadAllResources()) && apiOperation == null) { return true; } return false; } protected boolean isMethodOverridden(Method method, Class cls) { return ReflectionUtils.isOverriddenMethod(method, cls); } public void setApplication(Application application) { this.application = application; } /* Since 2.1.8 does nothing, as previous implementation maintained for ref in `ignoreOperationPathStrict` was ignoring resources which would be ignored due to other checks in Reader class. */ protected boolean ignoreOperationPath(String path, String parentPath) { return false; } protected boolean ignoreOperationPathStrict(String path, String parentPath) { if (StringUtils.isBlank(path) && StringUtils.isBlank(parentPath)) { return true; } else if (StringUtils.isNotBlank(path) && StringUtils.isBlank(parentPath)) { return false; } else if (StringUtils.isBlank(path) && StringUtils.isNotBlank(parentPath)) { return false; } if (parentPath != null && !parentPath.isEmpty() && !"/".equals(parentPath)) { if (!parentPath.startsWith("/")) { parentPath = "/" + parentPath; } if (parentPath.endsWith("/")) { parentPath = parentPath.substring(0, parentPath.length() - 1); } } if (path != null && !path.isEmpty() && !"/".equals(path)) { if (!path.startsWith("/")) { path = "/" + path; } if (path.endsWith("/")) { path = path.substring(0, path.length() - 1); } } return path.equals(parentPath); } protected Class getSubResourceWithJaxRsSubresourceLocatorSpecs(Method method) { final Class rawType = method.getReturnType(); final Class type; if (Class.class.equals(rawType)) { type = getClassArgument(method.getGenericReturnType()); if (type == null) { return null; } } else { type = rawType; } if (method.getAnnotation(javax.ws.rs.Path.class) != null) { if (ReaderUtils.extractOperationMethod(method, null) == null) { return type; } } return null; } private static Class getClassArgument(Type cls) { if (cls instanceof ParameterizedType) { final ParameterizedType parameterized = (ParameterizedType) cls; final Type[] args = parameterized.getActualTypeArguments(); if (args.length != 1) { LOGGER.error("Unexpected class definition: {}", cls); return null; } final Type first = args[0]; if (first instanceof Class) { return (Class) first; } else { return null; } } else { LOGGER.error("Unknown class definition: {}", cls); return null; } } /** * Comparator for uniquely sorting a collection of Method objects. * Supports overloaded methods (with the same name). * * @see Method */ private static class MethodComparator implements Comparator { @Override public int compare(Method m1, Method m2) { // First compare the names of the method int val = m1.getName().compareTo(m2.getName()); // If the names are equal, compare each argument type if (val == 0) { val = m1.getParameterTypes().length - m2.getParameterTypes().length; if (val == 0) { Class[] types1 = m1.getParameterTypes(); Class[] types2 = m2.getParameterTypes(); for (int i = 0; i < types1.length; i++) { val = types1[i].getName().compareTo(types2[i].getName()); if (val != 0) { break; } } } } return val; } } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ReaderListener.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.oas.integration.api.OpenApiReader; import io.swagger.v3.oas.models.OpenAPI; /** * Listener providing hooks for customizing automatically generated OpenAPI definitions in a JAX-RS * environment. Any classes picked up during the scanning process implementing this interface will * be instantiated via newInstance() and invoked before and after generating OpenAPI definitions, allowing * code to add additional data or change the generated definition. */ public interface ReaderListener { /** * Called before the OpenAPI definition gets populated from scanned classes. Use this method to * pre-process the OpenAPI definition before it gets populated. * * @param reader the reader used to read annotations and build the openAPI definition * @param openAPI the initial OpenAPI definition */ void beforeScan(OpenApiReader reader, OpenAPI openAPI); /** * Called after a OpenAPI definition has been populated from scanned classes. Use this method to * post-process OpenAPI definitions. * * @param reader the reader used to read annotations and build the OpenAPI definition * @param openAPI the configured OpenAPI definition */ void afterScan(OpenApiReader reader, OpenAPI openAPI); } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ResolvedParameter.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.oas.models.parameters.Parameter; import java.util.ArrayList; import java.util.List; public class ResolvedParameter { public List parameters = new ArrayList<>(); public Parameter requestBody; public List formParameters = new ArrayList<>(); } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/SecurityParser.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.oas.annotations.security.OAuthScope; import io.swagger.v3.oas.models.security.OAuthFlow; import io.swagger.v3.oas.models.security.OAuthFlows; import io.swagger.v3.oas.models.security.Scopes; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; public class SecurityParser { public static class SecuritySchemePair { public String key; public SecurityScheme securityScheme; } public static Optional> getSecurityRequirements(io.swagger.v3.oas.annotations.security.SecurityRequirement[] securityRequirementsApi) { if (securityRequirementsApi == null || securityRequirementsApi.length == 0) { return Optional.empty(); } List securityRequirements = new ArrayList<>(); for (io.swagger.v3.oas.annotations.security.SecurityRequirement securityRequirementApi : securityRequirementsApi) { SecurityRequirement securityRequirement = new SecurityRequirement(); if (securityRequirementApi.combine().length > 0) { for (io.swagger.v3.oas.annotations.security.SecurityRequirementEntry entry : securityRequirementApi.combine()) { if (StringUtils.isBlank(entry.name())) { continue; } if (entry.scopes().length > 0) { securityRequirement.addList(entry.name(), Arrays.asList(entry.scopes())); } else { securityRequirement.addList(entry.name()); } } } else { if (StringUtils.isBlank(securityRequirementApi.name())) { continue; } if (securityRequirementApi.scopes().length > 0) { securityRequirement.addList(securityRequirementApi.name(), Arrays.asList(securityRequirementApi.scopes())); } else { securityRequirement.addList(securityRequirementApi.name()); } } securityRequirements.add(securityRequirement); } if (securityRequirements.isEmpty()) { return Optional.empty(); } return Optional.of(securityRequirements); } public static Optional getSecurityScheme(io.swagger.v3.oas.annotations.security.SecurityScheme securityScheme) { if (securityScheme == null) { return Optional.empty(); } String key = null; SecurityScheme securitySchemeObject = new SecurityScheme(); if (StringUtils.isNotBlank(securityScheme.in().toString())) { securitySchemeObject.setIn(getIn(securityScheme.in().toString())); } if (StringUtils.isNotBlank(securityScheme.type().toString())) { securitySchemeObject.setType(getType(securityScheme.type().toString())); } if (StringUtils.isNotBlank(securityScheme.openIdConnectUrl())) { securitySchemeObject.setOpenIdConnectUrl(securityScheme.openIdConnectUrl()); } if (StringUtils.isNotBlank(securityScheme.scheme())) { securitySchemeObject.setScheme(securityScheme.scheme()); } if (StringUtils.isNotBlank(securityScheme.bearerFormat())) { securitySchemeObject.setBearerFormat(securityScheme.bearerFormat()); } if (StringUtils.isNotBlank(securityScheme.description())) { securitySchemeObject.setDescription(securityScheme.description()); } if (StringUtils.isNotBlank(securityScheme.paramName())) { securitySchemeObject.setName(securityScheme.paramName()); } if (StringUtils.isNotBlank(securityScheme.ref())) { securitySchemeObject.set$ref(securityScheme.ref()); } if (StringUtils.isNotBlank(securityScheme.name())) { key = securityScheme.name(); } if (securityScheme.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(securityScheme.extensions()); if (extensions != null) { extensions.forEach(securitySchemeObject::addExtension); } } getOAuthFlows(securityScheme.flows()).ifPresent(securitySchemeObject::setFlows); SecuritySchemePair result = new SecuritySchemePair(); result.key = key; result.securityScheme = securitySchemeObject; return Optional.of(result); } public static Optional getOAuthFlows(io.swagger.v3.oas.annotations.security.OAuthFlows oAuthFlows) { if (isEmpty(oAuthFlows)) { return Optional.empty(); } OAuthFlows oAuthFlowsObject = new OAuthFlows(); if (oAuthFlows.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(oAuthFlows.extensions()); if (extensions != null) { extensions.forEach(oAuthFlowsObject::addExtension); } } getOAuthFlow(oAuthFlows.authorizationCode()).ifPresent(oAuthFlowsObject::setAuthorizationCode); getOAuthFlow(oAuthFlows.clientCredentials()).ifPresent(oAuthFlowsObject::setClientCredentials); getOAuthFlow(oAuthFlows.implicit()).ifPresent(oAuthFlowsObject::setImplicit); getOAuthFlow(oAuthFlows.password()).ifPresent(oAuthFlowsObject::setPassword); return Optional.of(oAuthFlowsObject); } public static Optional getOAuthFlow(io.swagger.v3.oas.annotations.security.OAuthFlow oAuthFlow) { if (isEmpty(oAuthFlow)) { return Optional.empty(); } OAuthFlow oAuthFlowObject = new OAuthFlow(); if (StringUtils.isNotBlank(oAuthFlow.authorizationUrl())) { oAuthFlowObject.setAuthorizationUrl(oAuthFlow.authorizationUrl()); } if (StringUtils.isNotBlank(oAuthFlow.refreshUrl())) { oAuthFlowObject.setRefreshUrl(oAuthFlow.refreshUrl()); } if (StringUtils.isNotBlank(oAuthFlow.tokenUrl())) { oAuthFlowObject.setTokenUrl(oAuthFlow.tokenUrl()); } if (oAuthFlow.extensions().length > 0) { Map extensions = AnnotationsUtils.getExtensions(oAuthFlow.extensions()); if (extensions != null) { extensions.forEach(oAuthFlowObject::addExtension); } } getScopes(oAuthFlow.scopes()).ifPresent(oAuthFlowObject::setScopes); return Optional.of(oAuthFlowObject); } public static Optional getScopes(OAuthScope[] scopes) { if (isEmpty(scopes)) { return Optional.empty(); } Scopes scopesObject = new Scopes(); for (OAuthScope scope : scopes) { scopesObject.addString(scope.name(), scope.description()); } return Optional.of(scopesObject); } private static SecurityScheme.In getIn(String value) { return Arrays.stream(SecurityScheme.In.values()).filter(i -> i.toString().equals(value)).findFirst().orElse(null); } private static SecurityScheme.Type getType(String value) { return Arrays.stream(SecurityScheme.Type.values()).filter(i -> i.toString().equals(value)).findFirst().orElse(null); } private static boolean isEmpty(io.swagger.v3.oas.annotations.security.OAuthFlows oAuthFlows) { if (oAuthFlows == null) { return true; } if (!isEmpty(oAuthFlows.implicit())) { return false; } if (!isEmpty(oAuthFlows.authorizationCode())) { return false; } if (!isEmpty(oAuthFlows.clientCredentials())) { return false; } if (!isEmpty(oAuthFlows.password())) { return false; } return oAuthFlows.extensions().length == 0; } private static boolean isEmpty(io.swagger.v3.oas.annotations.security.OAuthFlow oAuthFlow) { if (oAuthFlow == null) { return true; } if (!StringUtils.isBlank(oAuthFlow.authorizationUrl())) { return false; } if (!StringUtils.isBlank(oAuthFlow.refreshUrl())) { return false; } if (!StringUtils.isBlank(oAuthFlow.tokenUrl())) { return false; } if (!isEmpty(oAuthFlow.scopes())) { return false; } return oAuthFlow.extensions().length == 0; } private static boolean isEmpty(OAuthScope[] scopes) { return scopes == null || scopes.length == 0; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/SwaggerSerializers.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.models.OpenAPI; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import java.io.IOException; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; @Provider @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, "application/yaml"}) public class SwaggerSerializers implements MessageBodyWriter { static boolean prettyPrint = false; static boolean openapi31 = false; public static void setPrettyPrint(boolean shouldPrettyPrint) { SwaggerSerializers.prettyPrint = shouldPrettyPrint; } public static void setOpenapi31(boolean openapi31) { SwaggerSerializers.openapi31 = openapi31; } @Override public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return OpenAPI.class.isAssignableFrom(type); } @Override public long getSize(OpenAPI data, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1L; } @Override public void writeTo(OpenAPI data, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap headers, OutputStream out) throws IOException { if (mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)) { if (prettyPrint) { if (openapi31) { out.write(Json31.pretty().writeValueAsBytes(data)); } else { out.write(Json.pretty().writeValueAsBytes(data)); } } else { if (openapi31) { out.write(Json31.mapper().writeValueAsBytes(data)); } else { out.write(Json.mapper().writeValueAsBytes(data)); } } } else if (mediaType.toString().startsWith("application/yaml")) { headers.remove("Content-Type"); headers.add("Content-Type", "application/yaml"); if (prettyPrint) { if (openapi31) { out.write(Yaml31.pretty().writeValueAsBytes(data)); } else { out.write(Yaml.pretty().writeValueAsBytes(data)); } } else { if (openapi31) { out.write(Yaml31.mapper().writeValueAsBytes(data)); } else { out.write(Yaml.mapper().writeValueAsBytes(data)); } } } else if (mediaType.isCompatible(MediaType.APPLICATION_XML_TYPE)) { headers.remove("Content-Type"); headers.add("Content-Type", MediaType.APPLICATION_JSON); if (prettyPrint) { if (openapi31) { out.write(Json31.pretty().writeValueAsBytes(data)); } else { out.write(Json.pretty().writeValueAsBytes(data)); } } else { if (openapi31) { out.write(Json31.mapper().writeValueAsBytes(data)); } else { out.write(Json.mapper().writeValueAsBytes(data)); } } } } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/AbstractOpenAPIExtension.java ================================================ package io.swagger.v3.jaxrs2.ext; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.jaxrs2.ResolvedParameter; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.media.Schema; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Iterator; import java.util.List; import java.util.Set; public abstract class AbstractOpenAPIExtension implements OpenAPIExtension { protected boolean openapi31; protected Schema.SchemaResolution schemaResolution; protected Configuration configuration = new Configuration(); @Override public String extractOperationMethod(Method method, Iterator chain) { if (chain.hasNext()) { return chain.next().extractOperationMethod(method, chain); } else { return null; } } @Override public ResolvedParameter extractParameters(List annotations, Type type, Set typesToSkip, Components components, javax.ws.rs.Consumes classConsumes, javax.ws.rs.Consumes methodConsumes, boolean includeRequestBody, JsonView jsonViewAnnotation, Iterator chain) { if (chain.hasNext()) { return chain.next().extractParameters(annotations, type, typesToSkip, components, classConsumes, methodConsumes, includeRequestBody, jsonViewAnnotation, chain); } else { return new ResolvedParameter(); } } @Override public void decorateOperation(Operation operation, Method method, Iterator chain) { if (chain.hasNext()) { chain.next().decorateOperation(operation, method, chain); } } protected boolean shouldIgnoreClass(Class cls) { return false; } protected boolean shouldIgnoreType(Type type, Set typesToSkip) { if (typesToSkip.contains(type)) { return true; } if (shouldIgnoreClass(constructType(type).getRawClass())) { typesToSkip.add(type); return true; } return false; } protected JavaType constructType(Type type) { return TypeFactory.defaultInstance().constructType(type); } @Override public void setOpenAPI31(boolean openapi31) { this.openapi31 = openapi31; } @Override public void setSchemaResolution(Schema.SchemaResolution schemaResolution) { this.schemaResolution = schemaResolution; } @Override public void setConfiguration(Configuration configuration) { this.configuration = configuration; if (configuration != null) { this.openapi31 = configuration.isOpenAPI31() != null ? configuration.isOpenAPI31() : false; this.schemaResolution = configuration.getSchemaResolution(); } } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/OpenAPIExtension.java ================================================ package io.swagger.v3.jaxrs2.ext; import com.fasterxml.jackson.annotation.JsonView; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.jaxrs2.ResolvedParameter; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.media.Schema; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Iterator; import java.util.List; import java.util.Set; public interface OpenAPIExtension { String extractOperationMethod(Method method, Iterator chain); ResolvedParameter extractParameters(List annotations, Type type, Set typesToSkip, Components components, javax.ws.rs.Consumes classConsumes, javax.ws.rs.Consumes methodConsumes, boolean includeRequestBody, JsonView jsonViewAnnotation, Iterator chain); /** * Decorates operation with additional vendor based extensions. * * @param operation the operation, build from swagger definition * @param method the method for additional scan * @param chain the chain with swagger extensions to process */ void decorateOperation(Operation operation, Method method, Iterator chain); default void setOpenAPI31(boolean openapi31) { //todo: override me! } default void setSchemaResolution(Schema.SchemaResolution schemaResolution) { //todo: override me! } default void setConfiguration(Configuration configuration) { //todo: override me! } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/ext/OpenAPIExtensions.java ================================================ package io.swagger.v3.jaxrs2.ext; import io.swagger.v3.jaxrs2.DefaultParameterExtension; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; public class OpenAPIExtensions { private static final Logger LOGGER = LoggerFactory.getLogger(OpenAPIExtensions.class); private static List extensions = null; public static List getExtensions() { return extensions; } public static void setExtensions(List ext) { extensions = ext; } public static Iterator chain() { return extensions.iterator(); } static { extensions = new ArrayList<>(); ServiceLoader loader = ServiceLoader.load(OpenAPIExtension.class, OpenAPIExtensions.class.getClassLoader()); for (OpenAPIExtension ext : loader) { LOGGER.debug("adding extension {}", ext); extensions.add(ext); } extensions.add(new DefaultParameterExtension()); } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/JaxrsAnnotationScanner.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.github.classgraph.ClassGraph; import io.github.classgraph.ScanResult; import io.swagger.v3.jaxrs2.integration.api.JaxrsOpenApiScanner; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Webhooks; import io.swagger.v3.oas.integration.IgnoredPackages; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public class JaxrsAnnotationScanner> implements JaxrsOpenApiScanner { static final Set ignored = new HashSet<>(); static { ignored.addAll(IgnoredPackages.ignored); } protected OpenAPIConfiguration openApiConfiguration; protected Application application; protected static final Logger LOGGER = LoggerFactory.getLogger(JaxrsAnnotationScanner.class); protected boolean onlyConsiderResourcePackages = false; public JaxrsAnnotationScanner application(Application application) { this.application = application; return this; } @Override public void setApplication(Application application) { this.application = application; } public T openApiConfiguration(OpenAPIConfiguration openApiConfiguration) { this.openApiConfiguration = openApiConfiguration; return (T) this; } @Override public void setConfiguration(OpenAPIConfiguration openApiConfiguration) { this.openApiConfiguration = openApiConfiguration; } @Override public Set> classes() { if (openApiConfiguration == null) { openApiConfiguration = new SwaggerConfiguration(); } ClassGraph graph = new ClassGraph().enableAllInfo(); Set acceptablePackages = new HashSet<>(); Set> output = new HashSet<>(); // if classes are passed, use them if (openApiConfiguration.getResourceClasses() != null && !openApiConfiguration.getResourceClasses().isEmpty()) { for (String className : openApiConfiguration.getResourceClasses()) { if (!isIgnored(className)) { try { output.add(Class.forName(className)); } catch (ClassNotFoundException e) { LOGGER.warn("error loading class from resourceClasses: " + e.getMessage(), e); } } } return output; } boolean allowAllPackages = false; if (openApiConfiguration.getResourcePackages() != null && !openApiConfiguration.getResourcePackages().isEmpty()) { for (String pkg : openApiConfiguration.getResourcePackages()) { if (!isIgnored(pkg)) { acceptablePackages.add(pkg); graph.whitelistPackages(pkg); } } } else { if (!onlyConsiderResourcePackages) { allowAllPackages = true; } } final Set> classes; try (ScanResult scanResult = graph.scan()) { classes = new HashSet<>(scanResult.getClassesWithAnnotation(javax.ws.rs.Path.class.getName()).loadClasses()); classes.addAll(new HashSet<>(scanResult.getClassesWithAnnotation(OpenAPIDefinition.class.getName()).loadClasses())); classes.addAll(new HashSet<>(scanResult.getClassesWithAnnotation(Webhooks.class.getName()).loadClasses())); if (Boolean.TRUE.equals(openApiConfiguration.isAlwaysResolveAppPath())) { classes.addAll(new HashSet<>(scanResult.getClassesWithAnnotation(ApplicationPath.class.getName()).loadClasses())); } } for (Class cls : classes) { if (allowAllPackages) { output.add(cls); } else { for (String pkg : acceptablePackages) { if (cls.getPackage().getName().startsWith(pkg)) { output.add(cls); } } } } LOGGER.trace("classes() - output size {}", output.size()); return output; } protected boolean isIgnored(String classOrPackageName) { if (StringUtils.isBlank(classOrPackageName)) { return true; } return ignored.stream().anyMatch(classOrPackageName::startsWith); } @Override public Map resources() { return new HashMap<>(); } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/JaxrsApplicationAndAnnotationScanner.java ================================================ package io.swagger.v3.jaxrs2.integration; import java.util.HashSet; import java.util.Set; public class JaxrsApplicationAndAnnotationScanner extends JaxrsAnnotationScanner { @Override public Set> classes() { Set> classes = super.classes(); Set> output = new HashSet<>(); if (application != null) { Set> clzs = application.getClasses(); if (clzs != null) { for (Class clz : clzs) { if (!isIgnored(clz.getName())) { output.add(clz); } } } Set singletons = application.getSingletons(); if (singletons != null) { for (Object o : singletons) { if (!isIgnored(o.getClass().getName())) { output.add(o.getClass()); } } } } classes.addAll(output); return classes; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/JaxrsApplicationAndResourcePackagesAnnotationScanner.java ================================================ package io.swagger.v3.jaxrs2.integration; import java.util.HashSet; import java.util.Set; /** * @since 2.0.10 */ public class JaxrsApplicationAndResourcePackagesAnnotationScanner extends JaxrsAnnotationScanner { public JaxrsApplicationAndResourcePackagesAnnotationScanner() { onlyConsiderResourcePackages = true; } @Override public Set> classes() { Set> classes = super.classes(); Set> output = new HashSet<>(); if (application != null) { Set> clzs = application.getClasses(); if (clzs != null) { for (Class clz : clzs) { if (!isIgnored(clz.getName())) { output.add(clz); } } } Set singletons = application.getSingletons(); if (singletons != null) { for (Object o : singletons) { if (!isIgnored(o.getClass().getName())) { output.add(o.getClass()); } } } } classes.addAll(output); return classes; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/JaxrsApplicationScanner.java ================================================ package io.swagger.v3.jaxrs2.integration; import java.util.HashSet; import java.util.Set; public class JaxrsApplicationScanner extends JaxrsAnnotationScanner { @Override public Set> classes() { Set> output = new HashSet<>(); if (application != null) { Set> clzs = application.getClasses(); if (clzs != null) { for (Class clz : clzs) { if (!isIgnored(clz.getName())) { output.add(clz); } } } Set singletons = application.getSingletons(); if (singletons != null) { for (Object o : singletons) { if (!isIgnored(o.getClass().getName())) { output.add(o.getClass()); } } } } return output; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/JaxrsOpenApiContext.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.swagger.v3.jaxrs2.Reader; import io.swagger.v3.jaxrs2.integration.api.JaxrsOpenApiScanner; import io.swagger.v3.oas.integration.GenericOpenApiContext; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.integration.api.OpenApiReader; import io.swagger.v3.oas.integration.api.OpenApiScanner; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ws.rs.core.Application; public class JaxrsOpenApiContext extends GenericOpenApiContext implements OpenApiContext { Logger LOGGER = LoggerFactory.getLogger(JaxrsOpenApiContext.class); private Application app; public T app(Application app) { this.app = app; return (T) this; } @Override protected OpenApiReader buildReader(OpenAPIConfiguration openApiConfiguration) throws Exception { OpenApiReader reader; if (StringUtils.isNotBlank(openApiConfiguration.getReaderClass())) { Class cls = getClass().getClassLoader().loadClass(openApiConfiguration.getReaderClass()); reader = (OpenApiReader) cls.newInstance(); } else { reader = new Reader(); } if (reader instanceof Reader) { ((Reader) reader).setApplication(app); } reader.setConfiguration(openApiConfiguration); return reader; } @Override protected OpenApiScanner buildScanner(OpenAPIConfiguration openApiConfiguration) throws Exception { OpenApiScanner scanner; if (StringUtils.isNotBlank(openApiConfiguration.getScannerClass())) { Class cls = getClass().getClassLoader().loadClass(openApiConfiguration.getScannerClass()); scanner = (OpenApiScanner) cls.newInstance(); } else { scanner = new JaxrsApplicationAndAnnotationScanner(); } scanner.setConfiguration(openApiConfiguration); if (scanner instanceof JaxrsOpenApiScanner) { ((JaxrsOpenApiScanner) scanner).setApplication(app); } return scanner; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/JaxrsOpenApiContextBuilder.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.swagger.v3.oas.integration.GenericOpenApiContextBuilder; import io.swagger.v3.oas.integration.OpenApiConfigurationException; import io.swagger.v3.oas.integration.OpenApiContextLocator; import io.swagger.v3.oas.integration.api.OpenApiContext; import org.apache.commons.lang3.StringUtils; import javax.servlet.ServletConfig; import javax.ws.rs.core.Application; public class JaxrsOpenApiContextBuilder extends GenericOpenApiContextBuilder { protected Application application; protected ServletConfig servletConfig; @Override public OpenApiContext buildContext(boolean init) throws OpenApiConfigurationException { if (StringUtils.isBlank(ctxId)) { ctxId = OpenApiContext.OPENAPI_CONTEXT_ID_DEFAULT; } OpenApiContext ctx = OpenApiContextLocator.getInstance().getOpenApiContext(ctxId); if (ctx == null) { OpenApiContext rootCtx = OpenApiContextLocator.getInstance().getOpenApiContext(OpenApiContext.OPENAPI_CONTEXT_ID_DEFAULT); ctx = new XmlWebOpenApiContext() .servletConfig(servletConfig) .app(application) .openApiConfiguration(openApiConfiguration) .id(ctxId) .parent(rootCtx); if (ctx.getConfigLocation() == null && configLocation != null) { ((XmlWebOpenApiContext) ctx).configLocation(configLocation); } if (((XmlWebOpenApiContext) ctx).getResourcePackages() == null && resourcePackages != null) { ((XmlWebOpenApiContext) ctx).resourcePackages(resourcePackages); } if (((XmlWebOpenApiContext) ctx).getResourceClasses() == null && resourceClasses != null) { ((XmlWebOpenApiContext) ctx).resourceClasses(resourceClasses); } if (init) { ctx.init(); // includes registering itself with OpenApiContextLocator } } return ctx; } public Application getApplication() { return application; } public void setApplication(Application application) { this.application = application; } public ServletConfig getServletConfig() { return servletConfig; } public void setServletConfig(ServletConfig servletConfig) { this.servletConfig = servletConfig; } public T application(Application application) { this.application = application; return (T) this; } public T servletConfig(ServletConfig servletConfig) { this.servletConfig = servletConfig; return (T) this; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/OpenApiServlet.java ================================================ package io.swagger.v3.jaxrs2.integration; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import io.swagger.v3.core.filter.OpenAPISpecFilter; import io.swagger.v3.core.filter.SpecFilter; import io.swagger.v3.jaxrs2.util.ServletUtils; import io.swagger.v3.oas.integration.OpenApiConfigurationException; import io.swagger.v3.oas.integration.OpenApiContextLocator; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.getContextIdFromServletConfig; public class OpenApiServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(OpenApiServlet.class); public static final String APPLICATION_JSON = "application/json"; public static final String APPLICATION_YAML = "application/yaml"; public static final String ACCEPT_HEADER = "Accept"; @Override public void init(ServletConfig config) throws ServletException { super.init(config); String ctxId = getContextIdFromServletConfig(config); try { new ServletOpenApiContextBuilder() .servletConfig(config) .ctxId(ctxId) .buildContext(true); } catch (OpenApiConfigurationException e) { LOGGER.error("Failed to initialize OpenAPI servlet context", e); } } // TODO move to own servlet non jaxrs project and reference from there // TODO cleanup and errors @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String ctxId = getContextIdFromServletConfig(getServletConfig()); OpenApiContext ctx = OpenApiContextLocator.getInstance().getOpenApiContext(ctxId); OpenAPI oas = ctx.read(); if (oas != null && ctx.getOpenApiConfiguration() != null) { if (ctx.getOpenApiConfiguration().getFilterClass() != null) { try { OpenAPISpecFilter filterImpl = (OpenAPISpecFilter) Class.forName(ctx.getOpenApiConfiguration().getFilterClass()).newInstance(); SpecFilter f = new SpecFilter(); oas = f.filter(oas, filterImpl, ServletUtils.getQueryParams(req.getParameterMap()), ServletUtils.getCookies(req.getCookies()), ServletUtils.getHeaders(req)); } catch (Exception e) { LOGGER.error("failed to load filter", e); } } } String type = "json"; String acceptHeader = req.getHeader(ACCEPT_HEADER); if (!StringUtils.isBlank(acceptHeader) && acceptHeader.toLowerCase().contains(APPLICATION_YAML)) { type = "yaml"; } else { // check URL: if (req.getRequestURL().toString().toLowerCase().endsWith("yaml")) { type = "yaml"; } } boolean pretty = ctx.getOpenApiConfiguration() != null && Boolean.TRUE.equals(ctx.getOpenApiConfiguration().isPrettyPrint()); resp.setStatus(200); if (type.equalsIgnoreCase("yaml")) { resp.setContentType(APPLICATION_YAML); try (PrintWriter pw = resp.getWriter()) { pw.write(pretty ? ctx.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(oas) : ctx.getOutputYamlMapper().writeValueAsString(oas)); } } else { resp.setContentType(APPLICATION_JSON); try (PrintWriter pw = resp.getWriter()) { pw.write(pretty ? ctx.getOutputJsonMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(oas) : ctx.getOutputJsonMapper().writeValueAsString(oas)); } } } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletConfigContextUtils.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.swagger.v3.oas.integration.api.OpenApiContext; import org.apache.commons.lang3.StringUtils; import javax.servlet.ServletConfig; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Collectors; public class ServletConfigContextUtils { public static final String OPENAPI_CONFIGURATION_RESOURCEPACKAGE_KEY = "openApi.configuration.resourcePackages"; public static final String OPENAPI_CONFIGURATION_LOCATION_KEY = "openApi.configuration.location"; public static final String JERSEY1_PACKAGE_KEY = "com.sun.jersey.config.property.packages"; public static final String JERSEY2_PACKAGE_KEY = "jersey.config.server.provider.packages"; public static final String JERSEY2_CLASSES_KEY = "jersey.config.server.provider.classnames"; public static final String OPENAPI_CONFIGURATION_READER_KEY = "openApi.configuration.readerClass"; public static final String OPENAPI_CONFIGURATION_SCANNER_KEY = "openApi.configuration.scannerClass"; public static final String OPENAPI_CONFIGURATION_BUILDER_KEY = "openApi.configuration.builderClass"; public static final String OPENAPI_CONFIGURATION_PRETTYPRINT_KEY = "openApi.configuration.prettyPrint"; public static final String OPENAPI_CONFIGURATION_READALLRESOURCES_KEY = "openApi.configuration.readAllResources"; public static final String OPENAPI_CONFIGURATION_RESOURCECLASSES_KEY = "openApi.configuration.resourceClasses"; public static final String OPENAPI_CONFIGURATION_FILTER_KEY = "openApi.configuration.filterClass"; public static final String OPENAPI_CONFIGURATION_CACHE_TTL_KEY = "openApi.configuration.cacheTTL"; /** * @since 2.1.6 */ public static final String OPENAPI_CONFIGURATION_SORTOUTPUT_KEY = "openApi.configuration.sortOutput"; /** * @since 2.1.9 */ public static final String OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY = "openApi.configuration.alwaysResolveAppPath"; /** * @since 2.1.15 */ public static final String OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY = "openApi.configuration.skipResolveAppPath"; /** * @since 2.0.6 */ public static final String OPENAPI_CONFIGURATION_OBJECT_MAPPER_PROCESSOR_KEY = "openApi.configuration.objectMapperProcessorClass"; /** * @since 2.2.17 */ public static final String OPENAPI_CONFIGURATION_DEFAULT_RESPONSE_CODE_KEY = "openApi.configuration.defaultResponseCode"; /** * @since 2.2.29 */ public static final String OPENAPI_CONFIGURATION_GROUPS_VALIDATION_STRATEGY = "openApi.configuration.groupsValidationStrategy"; /** * @since 2.2.29 */ public static final String OPENAPI_CONFIGURATION_VALIDATOR_PROCESSOR_CLASS = "openApi.configuration.validatorProcessorClass"; /** * @since 2.0.6 */ public static final String OPENAPI_CONFIGURATION_MODEL_CONVERTERS_KEY = "openApi.configuration.modelConverterClasses"; /** * @since 2.2.0 */ public static final String OPENAPI_CONFIGURATION_OPENAPI_31_KEY = "openApi.configuration.openAPI31"; public static final String OPENAPI_CONFIGURATION_CONVERT_TO_OPENAPI_31_KEY = "openApi.configuration.convertToOpenAPI31"; /** * @since 2.2.24 */ public static final String OPENAPI_CONFIGURATION_SCHEMA_RESOLUTION_KEY = "openApi.configuration.schemaResolution"; /** * @since 2.2.28 */ public static final String OPENAPI_CONFIGURATION_OPENAPI_VERSION_KEY = "openApi.configuration.openAPIVersion"; public static Set resolveResourcePackages(ServletConfig servletConfig) { if (!isServletConfigAvailable(servletConfig)) { return null; } String resourcePackage = getInitParam(servletConfig, OPENAPI_CONFIGURATION_RESOURCEPACKAGE_KEY); if (resourcePackage == null) { // jersey 1 resourcePackage = getInitParam(servletConfig, JERSEY1_PACKAGE_KEY); if (resourcePackage != null) { resourcePackage = resourcePackage.replace(';', ','); } } if (resourcePackage == null) { // jersey 2 resourcePackage = getInitParam(servletConfig, JERSEY2_PACKAGE_KEY); if (resourcePackage != null) { resourcePackage = resourcePackage.replace(';', ','); } } if (StringUtils.isBlank(resourcePackage)) { return null; } return Arrays.stream(resourcePackage.split(",")).collect(Collectors.toSet()); } public static Set resolveResourceClasses(ServletConfig servletConfig) { if (!isServletConfigAvailable(servletConfig)) { return null; } String resourceClasses = getInitParam(servletConfig, OPENAPI_CONFIGURATION_RESOURCECLASSES_KEY); if (resourceClasses == null) { // jersey 2 resourceClasses = getInitParam(servletConfig, JERSEY2_CLASSES_KEY); if (resourceClasses != null) { resourceClasses = resourceClasses.replace(';', ','); } } if (StringUtils.isBlank(resourceClasses)) { return null; } return Arrays.stream(resourceClasses.split(",")).collect(Collectors.toSet()); } /** * @since 2.0.6 */ public static Set resolveModelConverterClasses(ServletConfig servletConfig) { if (!isServletConfigAvailable(servletConfig)) { return null; } String modelConverterClasses = getInitParam(servletConfig, OPENAPI_CONFIGURATION_MODEL_CONVERTERS_KEY); if (modelConverterClasses != null) { modelConverterClasses = modelConverterClasses.replace(';', ','); } if (StringUtils.isBlank(modelConverterClasses)) { return null; } return new LinkedHashSet<>(Arrays.stream(modelConverterClasses.split(",")).collect(Collectors.toSet())); } public static String getInitParam(ServletConfig sc, String paramKey) { if (!isServletConfigAvailable(sc)) { return null; } return sc.getInitParameter(paramKey); } public static Boolean getBooleanInitParam(ServletConfig sc, String paramKey) { String param = getInitParam(sc, paramKey); if (StringUtils.isBlank(param)) { return null; } return Boolean.parseBoolean(param); } public static Long getLongInitParam(ServletConfig sc, String paramKey) { String param = getInitParam(sc, paramKey); if (StringUtils.isBlank(param)) { return null; } try { return Long.parseLong(param); } catch (NumberFormatException e) { return null; } } public static String getContextIdFromServletConfig(ServletConfig config) { String ctxId = null; if (isServletConfigAvailable(config)) { ctxId = getInitParam(config, OpenApiContext.OPENAPI_CONTEXT_ID_KEY); if (StringUtils.isBlank(ctxId)) { ctxId = OpenApiContext.OPENAPI_CONTEXT_ID_PREFIX + "servlet." + config.getServletName(); } } if (StringUtils.isBlank(ctxId)) { ctxId = OpenApiContext.OPENAPI_CONTEXT_ID_DEFAULT; } return ctxId; } public static boolean isServletConfigAvailable(ServletConfig sc) { if (sc == null) { return false; } try { sc.getInitParameter("test"); } catch (Exception e) { return false; } return true; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletOpenApiConfigurationLoader.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.oas.integration.ClasspathOpenApiConfigurationLoader; import io.swagger.v3.oas.integration.FileOpenApiConfigurationLoader; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenAPIConfigBuilder; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiConfigurationLoader; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletConfig; import java.io.IOException; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_BUILDER_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_CACHE_TTL_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_FILTER_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_OBJECT_MAPPER_PROCESSOR_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_DEFAULT_RESPONSE_CODE_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_GROUPS_VALIDATION_STRATEGY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_VALIDATOR_PROCESSOR_CLASS; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_OPENAPI_31_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_CONVERT_TO_OPENAPI_31_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_PRETTYPRINT_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_READALLRESOURCES_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_READER_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SCANNER_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SCHEMA_RESOLUTION_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_OPENAPI_VERSION_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_SORTOUTPUT_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.getBooleanInitParam; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.getInitParam; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.getLongInitParam; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.resolveModelConverterClasses; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.resolveResourceClasses; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.resolveResourcePackages; public class ServletOpenApiConfigurationLoader implements OpenApiConfigurationLoader { private static Logger LOGGER = LoggerFactory.getLogger(ServletOpenApiConfigurationLoader.class); private ServletConfig servletConfig; private FileOpenApiConfigurationLoader fileOpenApiConfigurationLoader = new FileOpenApiConfigurationLoader(); private ClasspathOpenApiConfigurationLoader classpathOpenApiConfigurationLoader = new ClasspathOpenApiConfigurationLoader(); public ServletOpenApiConfigurationLoader(ServletConfig servletConfig) { this.servletConfig = servletConfig; } @Override public OpenAPIConfiguration load(String path) throws IOException { if (servletConfig == null) { return null; } if (StringUtils.isBlank(path)) { // we want to resolve from servlet params SwaggerConfiguration configuration = new SwaggerConfiguration() .resourcePackages(resolveResourcePackages(servletConfig)) .filterClass(getInitParam(servletConfig, OPENAPI_CONFIGURATION_FILTER_KEY)) .resourceClasses(resolveResourceClasses(servletConfig)) .readAllResources(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_READALLRESOURCES_KEY)) .prettyPrint(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_PRETTYPRINT_KEY)) .sortOutput(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SORTOUTPUT_KEY)) .alwaysResolveAppPath(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY)) .skipResolveAppPath(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY)) .readerClass(getInitParam(servletConfig, OPENAPI_CONFIGURATION_READER_KEY)) .cacheTTL(getLongInitParam(servletConfig, OPENAPI_CONFIGURATION_CACHE_TTL_KEY)) .scannerClass(getInitParam(servletConfig, OPENAPI_CONFIGURATION_SCANNER_KEY)) .objectMapperProcessorClass(getInitParam(servletConfig, OPENAPI_CONFIGURATION_OBJECT_MAPPER_PROCESSOR_KEY)) .defaultResponseCode(getInitParam(servletConfig, OPENAPI_CONFIGURATION_DEFAULT_RESPONSE_CODE_KEY)) .validatorProcessorClass(getInitParam(servletConfig, OPENAPI_CONFIGURATION_VALIDATOR_PROCESSOR_CLASS)) .openAPI31(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_OPENAPI_31_KEY)) .convertToOpenAPI31(getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_CONVERT_TO_OPENAPI_31_KEY)) .modelConverterClasses(resolveModelConverterClasses(servletConfig)); if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_SCHEMA_RESOLUTION_KEY) != null) { configuration.schemaResolution(Schema.SchemaResolution.valueOf(getInitParam(servletConfig, OPENAPI_CONFIGURATION_SCHEMA_RESOLUTION_KEY))); } if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_OPENAPI_VERSION_KEY) != null) { configuration.openAPIVersion(getInitParam(servletConfig, OPENAPI_CONFIGURATION_OPENAPI_VERSION_KEY)); } if (StringUtils.isNotBlank(getInitParam(servletConfig, OPENAPI_CONFIGURATION_GROUPS_VALIDATION_STRATEGY))) { configuration.groupsValidationStrategy(Configuration.GroupsValidationStrategy.valueOf(getInitParam(servletConfig, OPENAPI_CONFIGURATION_GROUPS_VALIDATION_STRATEGY))); } return configuration; } String location = ServletConfigContextUtils.getInitParam(servletConfig, path); if (!StringUtils.isBlank(location)) { if (classpathOpenApiConfigurationLoader.exists(location)) { return classpathOpenApiConfigurationLoader.load(location); } else if (fileOpenApiConfigurationLoader.exists(location)) { return fileOpenApiConfigurationLoader.load(location); } } String builderClassName = getInitParam(servletConfig, OPENAPI_CONFIGURATION_BUILDER_KEY); if (StringUtils.isNotBlank(builderClassName)) { try { Class cls = getClass().getClassLoader().loadClass(builderClassName); // TODO instantiate with configuration OpenAPIConfigBuilder builder = (OpenAPIConfigBuilder) cls.newInstance(); return builder.build(); } catch (Exception e) { LOGGER.error("error loading builder: " + e.getMessage(), e); } } return null; } @Override public boolean exists(String path) { if (servletConfig == null) { return false; } if (StringUtils.isBlank(path)) { if (resolveResourcePackages(servletConfig) != null) { return true; } if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_FILTER_KEY) != null) { return true; } if (resolveResourceClasses(servletConfig) != null) { return true; } if (getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_READALLRESOURCES_KEY) != null) { return true; } if (getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_PRETTYPRINT_KEY) != null) { return true; } if (getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SORTOUTPUT_KEY) != null) { return true; } if (getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_ALWAYSRESOLVEAPPPATH_KEY) != null) { return true; } if (getBooleanInitParam(servletConfig, OPENAPI_CONFIGURATION_SKIPRESOLVEAPPPATH_KEY) != null) { return true; } if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_READER_KEY) != null) { return true; } if (getLongInitParam(servletConfig, OPENAPI_CONFIGURATION_CACHE_TTL_KEY) != null) { return true; } if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_SCANNER_KEY) != null) { return true; } if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_OBJECT_MAPPER_PROCESSOR_KEY) != null) { return true; } if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_DEFAULT_RESPONSE_CODE_KEY) != null) { return true; } if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_GROUPS_VALIDATION_STRATEGY) != null) { return true; } if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_VALIDATOR_PROCESSOR_CLASS) != null) { return true; } if (getInitParam(servletConfig, OPENAPI_CONFIGURATION_CONVERT_TO_OPENAPI_31_KEY) != null) { return true; } return resolveModelConverterClasses(servletConfig) != null; } String location = ServletConfigContextUtils.getInitParam(servletConfig, path); if (!StringUtils.isBlank(location)) { if (classpathOpenApiConfigurationLoader.exists(location)) { return true; } return fileOpenApiConfigurationLoader.exists(location); } return false; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletOpenApiContextBuilder.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.swagger.v3.oas.integration.GenericOpenApiContextBuilder; import io.swagger.v3.oas.integration.OpenApiConfigurationException; import io.swagger.v3.oas.integration.OpenApiContextLocator; import io.swagger.v3.oas.integration.api.OpenApiContext; import org.apache.commons.lang3.StringUtils; import javax.servlet.ServletConfig; public class ServletOpenApiContextBuilder extends GenericOpenApiContextBuilder { protected ServletConfig servletConfig; @Override public OpenApiContext buildContext(boolean init) throws OpenApiConfigurationException { if (StringUtils.isBlank(ctxId)) { ctxId = OpenApiContext.OPENAPI_CONTEXT_ID_DEFAULT; } OpenApiContext ctx = OpenApiContextLocator.getInstance().getOpenApiContext(ctxId); if (ctx == null) { OpenApiContext rootCtx = OpenApiContextLocator.getInstance().getOpenApiContext(OpenApiContext.OPENAPI_CONTEXT_ID_DEFAULT); ctx = new XmlWebOpenApiContext() .servletConfig(servletConfig) .openApiConfiguration(openApiConfiguration) .id(ctxId) .parent(rootCtx); if (ctx.getConfigLocation() == null && configLocation != null) { ((XmlWebOpenApiContext) ctx).configLocation(configLocation); } if (((XmlWebOpenApiContext) ctx).getResourcePackages() == null && resourcePackages != null) { ((XmlWebOpenApiContext) ctx).resourcePackages(resourcePackages); } if (((XmlWebOpenApiContext) ctx).getResourceClasses() == null && resourceClasses != null) { ((XmlWebOpenApiContext) ctx).resourceClasses(resourceClasses); } if (init) { ctx.init(); // includes registering itself with OpenApiContextLocator } } return ctx; } public ServletConfig getServletConfig() { return servletConfig; } public void setServletConfig(ServletConfig servletConfig) { this.servletConfig = servletConfig; } public T servletConfig(ServletConfig servletConfig) { this.servletConfig = servletConfig; return (T) this; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/ServletPathConfigurationLoader.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.swagger.v3.oas.integration.StringOpenApiConfigurationLoader; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import org.apache.commons.lang3.StringUtils; import javax.servlet.ServletConfig; import java.io.IOException; public class ServletPathConfigurationLoader implements StringOpenApiConfigurationLoader { private ServletConfig servletConfig; public ServletPathConfigurationLoader(ServletConfig servletConfig) { this.servletConfig = servletConfig; } @Override public OpenAPIConfiguration load(String path) throws IOException { if (servletConfig == null) { return null; } if (StringUtils.isBlank(path)) { return null; } String sanitized = (path.startsWith("/") ? path : "/" + path); String configString = readInputStreamToString(servletConfig.getServletContext().getResourceAsStream(sanitized)); return deserializeConfig(path, configString); } @Override public boolean exists(String path) { if (servletConfig == null) { return false; } if (StringUtils.isBlank(path)) { return false; } String sanitized = (path.startsWith("/") ? path : "/" + path); return servletConfig.getServletContext().getResourceAsStream(sanitized) != null; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/SwaggerLoader.java ================================================ package io.swagger.v3.jaxrs2.integration; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import io.swagger.v3.core.filter.OpenAPISpecFilter; import io.swagger.v3.core.filter.SpecFilter; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.integration.GenericOpenApiContextBuilder; import io.swagger.v3.oas.integration.OpenApiConfigurationException; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; public class SwaggerLoader { private String outputFormat; private String resourcePackages; private String resourceClasses; private String filterClass; private String readerClass; private String contextId; private String scannerClass; private Boolean prettyPrint = false; private Boolean readAllResources = Boolean.TRUE; private String ignoredRoutes; private String openapiAsString; private String objectMapperProcessorClass; private String defaultResponseCode; private Configuration.GroupsValidationStrategy groupsValidationStrategy = Configuration.GroupsValidationStrategy.DEFAULT; private String validatorProcessorClass; private String modelConverterClasses; private Boolean sortOutput = false; private Boolean alwaysResolveAppPath = false; private Boolean skipResolveAppPath = false; private Boolean openAPI31 = false; private Boolean convertToOpenAPI31 = false; private String schemaResolution; private String openAPIVersion; /** * @since 2.0.6 */ public String getObjectMapperProcessorClass() { return objectMapperProcessorClass; } /** * @since 2.0.6 */ public void setObjectMapperProcessorClass(String objectMapperProcessorClass) { this.objectMapperProcessorClass = objectMapperProcessorClass; } /** * @since 2.2.17 */ public String getDefaultResponseCode() { return defaultResponseCode; } /** * @since 2.2.17 */ public void setDefaultResponseCode(String defaultResponseCode) { this.defaultResponseCode = defaultResponseCode; } /** * @since 2.2.29 */ public String getGroupsValidationStrategy() { return groupsValidationStrategy.toString(); } /** * @since 2.2.29 */ public void setGroupsValidationStrategy(String groupsValidationStrategy) { if (StringUtils.isNotBlank(groupsValidationStrategy)) { this.groupsValidationStrategy = Configuration.GroupsValidationStrategy.valueOf(groupsValidationStrategy); } } /** * @since 2.2.29 */ public String getValidatorProcessorClass() { return validatorProcessorClass; } /** * @since 2.2.29 */ public void setValidatorProcessorClass(String validatorProcessorClass) { this.validatorProcessorClass = validatorProcessorClass; } /** * @since 2.0.6 */ public String getModelConverterClasses() { return modelConverterClasses; } /** * @since 2.0.6 */ public void setModelConverterClasses(String modelConverterClasses) { this.modelConverterClasses = modelConverterClasses; } public String getOutputFormat() { return outputFormat; } public void setOutputFormat(String outputFormat) { this.outputFormat = outputFormat; } public String getResourcePackages() { return resourcePackages; } public void setResourcePackages(String resourcePackages) { this.resourcePackages = resourcePackages; } public String getResourceClasses() { return resourceClasses; } public void setResourceClasses(String resourceClasses) { this.resourceClasses = resourceClasses; } public String getFilterClass() { return filterClass; } public void setFilterClass(String filterClass) { this.filterClass = filterClass; } /** * @since 2.0.6 */ public String getContextId() { return contextId; } /** * @since 2.0.6 */ public void setContextId(String contextId) { this.contextId = contextId; } public String getReaderClass() { return readerClass; } public void setReaderClass(String readerClass) { this.readerClass = readerClass; } public String getScannerClass() { return scannerClass; } public void setScannerClass(String scannerClass) { this.scannerClass = scannerClass; } public Boolean getPrettyPrint() { return prettyPrint; } public void setPrettyPrint(Boolean prettyPrint) { this.prettyPrint = prettyPrint; } public Boolean getReadAllResources() { return readAllResources; } public void setReadAllResources(Boolean readAllResources) { this.readAllResources = readAllResources; } public String getIgnoredRoutes() { return ignoredRoutes; } public void setIgnoredRoutes(String ignoredRoutes) { this.ignoredRoutes = ignoredRoutes; } public String getOpenapiAsString() { return openapiAsString; } public void setOpenapiAsString(String openapiAsString) { this.openapiAsString = openapiAsString; } /** * @since 2.1.6 */ public Boolean getSortOutput() { return sortOutput; } /** * @since 2.1.6 */ public void setSortOutput(Boolean sortOutput) { this.sortOutput = sortOutput; } /** * @since 2.1.9 */ public Boolean getAlwaysResolveAppPath() { return alwaysResolveAppPath; } /** * @since 2.1.9 */ public void setAlwaysResolveAppPath(Boolean alwaysResolveAppPath) { this.alwaysResolveAppPath = alwaysResolveAppPath; } /** * @since 2.1.15 */ public Boolean getSkipResolveAppPath() { return skipResolveAppPath; } /** * @since 2.1.15 */ public void setSkipResolveAppPath(Boolean skipResolveAppPath) { this.skipResolveAppPath = skipResolveAppPath; } public Boolean getOpenAPI31() { return openAPI31; } public Boolean getConvertToOpenAPI31() { return convertToOpenAPI31; } /** * @since 2.2.0 */ public void setOpenAPI31(Boolean openAPI31) { this.openAPI31 = openAPI31; } /** * @since 2.2.12 */ public void setConvertToOpenAPI31(Boolean convertToOpenAPI31) { this.convertToOpenAPI31 = convertToOpenAPI31; } /** * @since 2.2.24 */ public String getSchemaResolution() { return schemaResolution; } /** * @since 2.2.24 */ public void setSchemaResolution(String schemaResolution) { this.schemaResolution = schemaResolution; } /** * @since 2.2.28 */ public String getOpenAPIVersion() { return openAPIVersion; } /** * @since 2.2.28 */ public void setOpenAPIVersion(String openAPIVersion) { this.openAPIVersion = openAPIVersion; } public Map resolve() throws Exception{ Set ignoredRoutesSet = null; if (StringUtils.isNotBlank(ignoredRoutes)) { ignoredRoutesSet = new HashSet<>(Arrays.asList(ignoredRoutes.split(","))); } Set resourceClassesSet = null; if (StringUtils.isNotBlank(resourceClasses)) { resourceClassesSet = new HashSet<>(Arrays.asList(resourceClasses.split(","))); } Set resourcePackagesSet = null; if (StringUtils.isNotBlank(resourcePackages)) { resourcePackagesSet = new HashSet<>(Arrays.asList(resourcePackages.split(","))); } LinkedHashSet modelConverterSet = null; if (StringUtils.isNotBlank(modelConverterClasses)) { modelConverterSet = new LinkedHashSet<>(Arrays.asList(modelConverterClasses.split(","))); } OpenAPI openAPIInput = null; if (StringUtils.isNotBlank(openapiAsString)) { try { openAPIInput = Json.mapper().readValue(openapiAsString, OpenAPI.class); } catch (Exception e) { try { openAPIInput = Yaml.mapper().readValue(openapiAsString, OpenAPI.class); } catch (Exception e1) { throw new Exception("Error reading/deserializing openapi input: " + e.getMessage(), e); } } } SwaggerConfiguration config = new SwaggerConfiguration() .filterClass(filterClass) .ignoredRoutes(ignoredRoutesSet) .prettyPrint(prettyPrint) .readAllResources(readAllResources) .openAPI(openAPIInput) .readerClass(readerClass) .scannerClass(scannerClass) .resourceClasses(resourceClassesSet) .resourcePackages(resourcePackagesSet) .objectMapperProcessorClass(objectMapperProcessorClass) .defaultResponseCode(defaultResponseCode) .validatorProcessorClass(validatorProcessorClass) .groupsValidationStrategy(groupsValidationStrategy) .modelConverterClasses(modelConverterSet) .sortOutput(sortOutput) .alwaysResolveAppPath(alwaysResolveAppPath) .skipResolveAppPath(skipResolveAppPath) .openAPI31(openAPI31) .convertToOpenAPI31(convertToOpenAPI31); if (schemaResolution != null) { config.schemaResolution(Schema.SchemaResolution.valueOf(schemaResolution)); } if (openAPIVersion != null) { config.openAPIVersion(openAPIVersion); } try { GenericOpenApiContextBuilder builder = new JaxrsOpenApiContextBuilder() .openApiConfiguration(config); if (StringUtils.isNotBlank(contextId)) { builder.ctxId(contextId); } OpenApiContext context = builder.buildContext(true); OpenAPI openAPI = context.read(); if (StringUtils.isNotBlank(filterClass)) { try { OpenAPISpecFilter filterImpl = (OpenAPISpecFilter) this.getClass().getClassLoader().loadClass(filterClass).newInstance(); SpecFilter f = new SpecFilter(); openAPI = f.filter(openAPI, filterImpl, new HashMap<>(), new HashMap<>(), new HashMap<>()); } catch (Exception e) { throw new Exception("Error applying filter to API specification: " + e.getMessage(), e); } } String openapiJson = null; String openapiYaml = null; if ("JSON".equals(outputFormat) || "JSONANDYAML".equals(outputFormat)) { if (prettyPrint != null && prettyPrint) { openapiJson = context.getOutputJsonMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(openAPI); } else { openapiJson = context.getOutputJsonMapper().writeValueAsString(openAPI); } } if ("YAML".equals(outputFormat) || "JSONANDYAML".equals(outputFormat)) { if (prettyPrint != null && prettyPrint) { openapiYaml = context.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(openAPI); } else { openapiYaml = context.getOutputYamlMapper().writeValueAsString(openAPI); } } Map map = new HashMap<>(); map.put("JSON", openapiJson); map.put("YAML", openapiYaml); return map; } catch (OpenApiConfigurationException e) { throw new Exception("Error resolving API specification: " + e.getMessage(), e); } catch (Exception e) { throw new Exception("Error resolving API specification: " + e.getMessage(), e); } } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/XmlWebOpenApiContext.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.swagger.v3.jaxrs2.integration.api.WebOpenApiContext; import io.swagger.v3.oas.integration.api.OpenApiConfigurationLoader; import org.apache.commons.lang3.tuple.ImmutablePair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; public class XmlWebOpenApiContext> extends JaxrsOpenApiContext implements WebOpenApiContext { private ServletContext servletContext; private ServletConfig servletConfig; Logger LOGGER = LoggerFactory.getLogger(XmlWebOpenApiContext.class); @Override public ServletContext getServletContext() { return servletContext; } @Override public ServletConfig getServletConfig() { return servletConfig; } public T servletConfig(ServletConfig servletConfig) { if (!ServletConfigContextUtils.isServletConfigAvailable(servletConfig)) { return (T) this; } this.servletConfig = servletConfig; this.servletContext = servletConfig.getServletContext(); return (T) this; } @Override protected List> getKnownLocations() { List> locations = new LinkedList<>(Arrays.asList( new ImmutablePair<>("servlet", ServletConfigContextUtils.OPENAPI_CONFIGURATION_LOCATION_KEY), new ImmutablePair<>("servletpath", "openapi-configuration.yaml"), new ImmutablePair<>("servletpath", "openapi-configuration.json"), new ImmutablePair<>("servletpath", "WEB-INF/openapi-configuration.yaml"), new ImmutablePair<>("servletpath", "WEB-INF/openapi-configuration.json"), new ImmutablePair<>("servletpath", "openapi.yaml"), new ImmutablePair<>("servletpath", "openapi.json"), new ImmutablePair<>("servletpath", "WEB-INF/openapi.yaml"), new ImmutablePair<>("servletpath", "WEB-INF/openapi.json") )); locations.addAll(super.getKnownLocations()); locations.add(new ImmutablePair<>("servlet", "")); // get config from init params return locations; } @Override protected Map getLocationLoaders() { Map map = super.getLocationLoaders(); map.put("servlet", new ServletOpenApiConfigurationLoader(servletConfig)); map.put("servletpath", new ServletPathConfigurationLoader(servletConfig)); return map; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/api/JaxrsOpenApiScanner.java ================================================ package io.swagger.v3.jaxrs2.integration.api; import io.swagger.v3.oas.integration.api.OpenApiScanner; import javax.ws.rs.core.Application; public interface JaxrsOpenApiScanner extends OpenApiScanner { void setApplication(Application application); } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/api/WebOpenApiContext.java ================================================ package io.swagger.v3.jaxrs2.integration.api; import io.swagger.v3.oas.integration.api.OpenApiContext; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; public interface WebOpenApiContext extends OpenApiContext { ServletContext getServletContext(); ServletConfig getServletConfig(); } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/resources/AcceptHeaderOpenApiResource.java ================================================ package io.swagger.v3.jaxrs2.integration.resources; import io.swagger.v3.oas.annotations.Operation; import javax.servlet.ServletConfig; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Application; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; @Path("/openapi") public class AcceptHeaderOpenApiResource extends BaseOpenApiResource { @Context ServletConfig config; @Context Application app; @GET @Produces({MediaType.APPLICATION_JSON}) @Operation(hidden = true) public Response getOpenApiJson(@Context HttpHeaders headers, @Context UriInfo uriInfo) throws Exception { return super.getOpenApi(headers, config, app, uriInfo, "json"); } @GET @Produces({"application/yaml"}) @Operation(hidden = true) public Response getOpenApiYaml(@Context HttpHeaders headers, @Context UriInfo uriInfo) throws Exception { return super.getOpenApi(headers, config, app, uriInfo, "yaml"); } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/resources/BaseOpenApiResource.java ================================================ package io.swagger.v3.jaxrs2.integration.resources; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import io.swagger.v3.core.filter.OpenAPISpecFilter; import io.swagger.v3.core.filter.SpecFilter; import io.swagger.v3.jaxrs2.integration.JaxrsOpenApiContextBuilder; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletConfig; import javax.ws.rs.core.Application; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.getContextIdFromServletConfig; public abstract class BaseOpenApiResource { private static Logger LOGGER = LoggerFactory.getLogger(BaseOpenApiResource.class); protected String getContextId(ServletConfig config) { return getContextIdFromServletConfig(config); } protected Response getOpenApi(HttpHeaders headers, ServletConfig config, Application app, UriInfo uriInfo, String type) throws Exception { String ctxId = getContextId(config); OpenApiContext ctx = new JaxrsOpenApiContextBuilder() .servletConfig(config) .application(app) .resourcePackages(resourcePackages) .configLocation(configLocation) .openApiConfiguration(openApiConfiguration) .ctxId(ctxId) .buildContext(true); OpenAPI oas = ctx.read(); boolean pretty = ctx.getOpenApiConfiguration() != null && Boolean.TRUE.equals(ctx.getOpenApiConfiguration().isPrettyPrint()); if (oas != null && ctx.getOpenApiConfiguration() != null) { if (ctx.getOpenApiConfiguration().getFilterClass() != null) { try { OpenAPISpecFilter filterImpl = (OpenAPISpecFilter) Class.forName(ctx.getOpenApiConfiguration().getFilterClass()).newInstance(); SpecFilter f = new SpecFilter(); oas = f.filter(oas, filterImpl, getQueryParams(uriInfo.getQueryParameters()), getCookies(headers), getHeaders(headers)); } catch (Exception e) { LOGGER.error("failed to load filter", e); } } } if (oas == null) { return Response.status(404).build(); } if (StringUtils.isNotBlank(type) && type.trim().equalsIgnoreCase("yaml")) { return Response.status(Response.Status.OK) .entity(pretty ? ctx.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(oas) : ctx.getOutputYamlMapper().writeValueAsString(oas)) .type("application/yaml") .build(); } else { return Response.status(Response.Status.OK) .entity(pretty ? ctx.getOutputJsonMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(oas) : ctx.getOutputJsonMapper().writeValueAsString(oas)) .type(MediaType.APPLICATION_JSON_TYPE) .build(); } } private static Map> getQueryParams(MultivaluedMap params) { Map> output = new HashMap<>(); if (params != null) { params.forEach(output::put); } return output; } private static Map getCookies(HttpHeaders headers) { Map output = new HashMap<>(); if (headers != null) { headers.getCookies().forEach((k, v) -> output.put(k, v.getValue())); } return output; } private static Map> getHeaders(HttpHeaders headers) { Map> output = new HashMap<>(); if (headers != null) { headers.getRequestHeaders().forEach(output::put); } return output; } protected String configLocation; public String getConfigLocation() { return configLocation; } public void setConfigLocation(String configLocation) { this.configLocation = configLocation; } public BaseOpenApiResource configLocation(String configLocation) { setConfigLocation(configLocation); return this; } protected Set resourcePackages; public Set getResourcePackages() { return resourcePackages; } public void setResourcePackages(Set resourcePackages) { this.resourcePackages = resourcePackages; } public BaseOpenApiResource resourcePackages(Set resourcePackages) { setResourcePackages(resourcePackages); return this; } protected OpenAPIConfiguration openApiConfiguration; public OpenAPIConfiguration getOpenApiConfiguration() { return openApiConfiguration; } public void setOpenApiConfiguration(OpenAPIConfiguration openApiConfiguration) { this.openApiConfiguration = openApiConfiguration; } public BaseOpenApiResource openApiConfiguration(OpenAPIConfiguration openApiConfiguration) { setOpenApiConfiguration(openApiConfiguration); return this; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/integration/resources/OpenApiResource.java ================================================ package io.swagger.v3.jaxrs2.integration.resources; import io.swagger.v3.oas.annotations.Operation; import javax.servlet.ServletConfig; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Application; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; @Path("/openapi.{type:json|yaml}") public class OpenApiResource extends BaseOpenApiResource { @Context ServletConfig config; @Context Application app; @GET @Produces({MediaType.APPLICATION_JSON, "application/yaml"}) @Operation(hidden = true) public Response getOpenApi(@Context HttpHeaders headers, @Context UriInfo uriInfo, @PathParam("type") String type) throws Exception { return super.getOpenApi(headers, config, app, uriInfo, type); } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/util/ReaderUtils.java ================================================ package io.swagger.v3.jaxrs2.util; import com.fasterxml.jackson.annotation.JsonView; import io.swagger.v3.core.util.ParameterProcessor; import io.swagger.v3.core.util.ReflectionUtils; import io.swagger.v3.jaxrs2.ext.OpenAPIExtension; import io.swagger.v3.jaxrs2.ext.OpenAPIExtensions; import io.swagger.v3.oas.integration.api.OpenAPIConfiguration; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import org.apache.commons.lang3.StringUtils; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.Context; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Optional; public class ReaderUtils { private static final String GET_METHOD = "get"; private static final String POST_METHOD = "post"; private static final String PUT_METHOD = "put"; private static final String DELETE_METHOD = "delete"; private static final String HEAD_METHOD = "head"; private static final String OPTIONS_METHOD = "options"; private static final String PATH_DELIMITER = "/"; public static List collectConstructorParameters(Class cls, Components components, javax.ws.rs.Consumes classConsumes, JsonView jsonViewAnnotation) { return collectConstructorParameters(cls, components, classConsumes, jsonViewAnnotation, null); } public static List collectConstructorParameters(Class cls, Components components, javax.ws.rs.Consumes classConsumes, JsonView jsonViewAnnotation, Schema.SchemaResolution schemaResolution) { return collectConstructorParameters(cls, components, classConsumes, jsonViewAnnotation, schemaResolution, false); } /** * Collects constructor-level parameters from class. * * @param cls is a class for collecting * @param components * @return the collection of supported parameters */ public static List collectConstructorParameters(Class cls, Components components, javax.ws.rs.Consumes classConsumes, JsonView jsonViewAnnotation, Schema.SchemaResolution schemaResolution, boolean openapi31) { if (cls.isLocalClass() || (cls.isMemberClass() && !Modifier.isStatic(cls.getModifiers()))) { return Collections.emptyList(); } List selected = Collections.emptyList(); int maxParamsCount = 0; for (Constructor constructor : cls.getDeclaredConstructors()) { if (!ReflectionUtils.isConstructorCompatible(constructor) && !ReflectionUtils.isInject(Arrays.asList(constructor.getDeclaredAnnotations()))) { continue; } final Type[] genericParameterTypes = constructor.getGenericParameterTypes(); final Annotation[][] annotations = constructor.getParameterAnnotations(); int paramsCount = 0; final List parameters = new ArrayList<>(); for (int i = 0; i < genericParameterTypes.length; i++) { final List tmpAnnotations = Arrays.asList(annotations[i]); if (isContext(tmpAnnotations)) { paramsCount++; } else { final Type genericParameterType = genericParameterTypes[i]; final List tmpParameters = collectParameters(genericParameterType, tmpAnnotations, components, classConsumes, jsonViewAnnotation); if (! tmpParameters.isEmpty()) { for (Parameter tmpParameter : tmpParameters) { Parameter processedParameter = ParameterProcessor.applyAnnotations( tmpParameter, genericParameterType, tmpAnnotations, components, classConsumes == null ? new String[0] : classConsumes.value(), null, jsonViewAnnotation, openapi31, schemaResolution); if (processedParameter != null) { parameters.add(processedParameter); } } paramsCount++; } } } if (paramsCount >= maxParamsCount) { maxParamsCount = paramsCount; selected = parameters; } } return selected; } /** * Collects field-level parameters from class. * * @param cls is a class for collecting * @param components * @return the collection of supported parameters */ public static List collectFieldParameters(Class cls, Components components, javax.ws.rs.Consumes classConsumes, JsonView jsonViewAnnotation) { final List parameters = new ArrayList<>(); for (Field field : ReflectionUtils.getDeclaredFields(cls)) { final List annotations = Arrays.asList(field.getAnnotations()); final Type genericType = field.getGenericType(); parameters.addAll(collectParameters(genericType, annotations, components, classConsumes, jsonViewAnnotation)); } return parameters; } private static List collectParameters(Type type, List annotations, Components components, javax.ws.rs.Consumes classConsumes, JsonView jsonViewAnnotation) { final Iterator chain = OpenAPIExtensions.chain(); return chain.hasNext() ? chain.next().extractParameters(annotations, type, new HashSet<>(), components, classConsumes, null, false, jsonViewAnnotation, chain).parameters : Collections.emptyList(); } private static boolean isContext(List annotations) { for (Annotation annotation : annotations) { if (annotation instanceof Context) { return true; } } return false; } public static Optional> getStringListFromStringArray(String[] array) { if (array == null) { return Optional.empty(); } List list = new ArrayList<>(); boolean isEmpty = true; for (String value : array) { if (StringUtils.isNotBlank(value)) { isEmpty = false; } list.add(value); } if (isEmpty) { return Optional.empty(); } return Optional.of(list); } public static boolean isIgnored(String path, OpenAPIConfiguration config) { if (config.getIgnoredRoutes() == null) { return false; } for (String item : config.getIgnoredRoutes()) { final int length = item.length(); if (path.startsWith(item) && (path.length() == length || path.startsWith(PATH_DELIMITER, length))) { return true; } } return false; } public static String getPath(javax.ws.rs.Path classLevelPath, javax.ws.rs.Path methodLevelPath, String parentPath, boolean isSubresource) { if (classLevelPath == null && methodLevelPath == null && StringUtils.isEmpty(parentPath)) { return null; } StringBuilder b = new StringBuilder(); appendPathComponent(parentPath, b); if (classLevelPath != null && !isSubresource) { appendPathComponent(classLevelPath.value(), b); } if (methodLevelPath != null) { appendPathComponent(methodLevelPath.value(), b); } return b.length() == 0 ? "/" : b.toString(); } /** * appends a path component string to a StringBuilder * guarantees: *
    *
  • nulls, empty strings and "/" are nops
  • *
  • output will always start with "/" and never end with "/"
  • *
* @param component component to be added * @param to output */ private static void appendPathComponent(String component, StringBuilder to) { if (component == null || component.isEmpty() || "/".equals(component)) { return; } if (!component.startsWith("/") && (to.length() == 0 || '/' != to.charAt(to.length() - 1))) { to.append("/"); } if (component.endsWith("/")) { to.append(component, 0, component.length() - 1); } else { to.append(component); } } public static String extractOperationMethod(Method method, Iterator chain) { if (method.getAnnotation(javax.ws.rs.GET.class) != null) { return GET_METHOD; } else if (method.getAnnotation(javax.ws.rs.PUT.class) != null) { return PUT_METHOD; } else if (method.getAnnotation(javax.ws.rs.POST.class) != null) { return POST_METHOD; } else if (method.getAnnotation(javax.ws.rs.DELETE.class) != null) { return DELETE_METHOD; } else if (method.getAnnotation(javax.ws.rs.OPTIONS.class) != null) { return OPTIONS_METHOD; } else if (method.getAnnotation(javax.ws.rs.HEAD.class) != null) { return HEAD_METHOD; } else if (method.getAnnotation(HttpMethod.class) != null) { HttpMethod httpMethod = method.getAnnotation(HttpMethod.class); return httpMethod.value().toLowerCase(); } else if (!StringUtils.isEmpty(getHttpMethodFromCustomAnnotations(method))) { return getHttpMethodFromCustomAnnotations(method); } else if ((ReflectionUtils.getOverriddenMethod(method)) != null) { return extractOperationMethod(ReflectionUtils.getOverriddenMethod(method), chain); } else if (chain != null && chain.hasNext()) { return chain.next().extractOperationMethod(method, chain); } else { return null; } } public static String getHttpMethodFromCustomAnnotations(Method method) { for (Annotation methodAnnotation : method.getAnnotations()) { HttpMethod httpMethod = methodAnnotation.annotationType().getAnnotation(HttpMethod.class); if (httpMethod != null) { return httpMethod.value().toLowerCase(); } } return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/util/ServletUtils.java ================================================ package io.swagger.v3.jaxrs2.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.MultivaluedHashMap; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; public class ServletUtils { private static final Logger LOGGER = LoggerFactory.getLogger(ServletUtils.class); public static MultivaluedHashMap getQueryParams(Map parameterMap) { MultivaluedHashMap queryParameters = new MultivaluedHashMap<>(); if (parameterMap.size() == 0) { return queryParameters; } for (Map.Entry parameter : parameterMap.entrySet()) { for (String value : parameter.getValue()) { try { queryParameters.add(URLDecoder.decode(parameter.getKey(), StandardCharsets.UTF_8.name()), URLDecoder.decode(value, StandardCharsets.UTF_8.name())); } catch (UnsupportedEncodingException e) { LOGGER.error("Unable to decode query parameter", e); } } } return queryParameters; } public static Map getCookies(Cookie[] cookies) { Map mapOfCookies = new HashMap<>(); if (cookies != null) { for (Cookie cookie : cookies) { mapOfCookies.put(cookie.getName(), cookie.getValue()); } } return mapOfCookies; } public static Map> getHeaders(HttpServletRequest req) { if (req.getHeaderNames() == null) { return Collections.emptyMap(); } else { return Collections .list(req.getHeaderNames()) .stream() .collect(Collectors.toMap( Function.identity(), header -> Collections.list(req.getHeaders(header)))); } } } ================================================ FILE: modules/swagger-jaxrs2/src/main/resources/META-INF/beans.xml ================================================ ================================================ FILE: modules/swagger-jaxrs2/src/test/java/com/my/project/resources/ResourceInPackageA.java ================================================ package com.my.project.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.ArrayList; @Path("/packageA") public class ResourceInPackageA { @Operation(operationId = "test.") @GET public void getTest(@Parameter(name = "test") ArrayList tenantId) { return; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/com/my/sorted/resources/SortedThing.java ================================================ package com.my.sorted.resources; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/sorted") public class SortedThing { @Operation(operationId = "foo") @GET @Path("/pet") public Pet foo() { return null; } @Operation(operationId = "bar") @GET @Path("/pet") public Pet bar() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/BeanParamTest.java ================================================ package io.swagger.v3.jaxrs2; import java.util.List; import javax.ws.rs.BeanParam; import javax.ws.rs.GET; import javax.ws.rs.Path; import io.swagger.v3.jaxrs2.resources.model.NestedBeanParam; import io.swagger.v3.oas.models.media.IntegerSchema; import org.testng.Assert; import org.testng.annotations.Test; import io.swagger.v3.jaxrs2.resources.model.ListOfStringsBeanParam; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import static org.testng.Assert.assertEquals; public class BeanParamTest { @Path("/") private static class MyBeanParamResource { @GET public String getWithBeanParam(@BeanParam ListOfStringsBeanParam listOfStringsBean) { return "result"; } @GET @Path("/nested-param") public String getWithNestedBeanParam(@BeanParam NestedBeanParam listOfStringsBean) { return "result"; } } @Test(description = "check array type of serialized BeanParam containing QueryParams") // tests issue #2466 public void shouldSerializeTypeParameter() { OpenAPI openApi = new Reader(new OpenAPI()).read(MyBeanParamResource.class); List getOperationParams = openApi.getPaths().get("/").getGet().getParameters(); assertEquals(getOperationParams.size(), 1); Parameter param = getOperationParams.get(0); assertEquals(param.getName(), "listOfStrings"); Schema schema = param.getSchema(); // These are the important checks: assertEquals(schema.getClass(), ArraySchema.class); assertEquals(schema.getItems().getType(), "string"); } @Test(description = "check integer type of nested BeanParam containing a QueryParam") // tests issue #2466 public void shouldSerializeNestedTypeParameter() { OpenAPI openApi = new Reader(new OpenAPI()).read(MyBeanParamResource.class); List getOperationParams = openApi.getPaths().get("/nested-param").getGet().getParameters(); Assert.assertEquals(getOperationParams.size(), 1); Parameter queryParam = getOperationParams.get(0); Assert.assertEquals(queryParam.getName(), "queryParam"); Schema schema = queryParam.getSchema(); Assert.assertEquals(schema.getClass(), IntegerSchema.class); Assert.assertEquals(schema.getType(), "integer"); Assert.assertEquals(((IntegerSchema) schema).getDefault(), 10); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/BinaryParameterResourceTest.java ================================================ package io.swagger.v3.jaxrs2; import java.io.IOException; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.jaxrs2.resources.BinaryParameterResource; public class BinaryParameterResourceTest extends AbstractAnnotationTest { @Test(description = "check binary model serialization with base64", singleThreaded = true) // tests issue #2466 public void shouldSerializeBinaryParameterBase64() throws IOException { try { System.setProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY, Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_BASE64.toString()); compareAsYaml(BinaryParameterResource.class, getOpenAPIAsString("BinaryParameterResource.yaml")); } finally { System.clearProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY); } } @BeforeTest public void before() { System.clearProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY); } @AfterTest public void after() { System.clearProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY); } @Test(description = "check binary model serialization with StringSchema", singleThreaded = true) // tests issue #2466 public void shouldSerializeBinaryParameterStringSchema() throws IOException { try { System.setProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY, Schema.BynaryStringConversion.BINARY_STRING_CONVERSION_STRING_SCHEMA.toString()); compareAsYaml(BinaryParameterResource.class, getOpenAPIAsString("BinaryParameterResource.yaml")); } finally { System.clearProperty(Schema.BINARY_STRING_CONVERSION_PROPERTY); } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/BootstrapServlet.java ================================================ package io.swagger.v3.jaxrs2; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import io.swagger.v3.jaxrs2.integration.JaxrsOpenApiContextBuilder; import io.swagger.v3.oas.integration.OpenApiConfigurationException; import io.swagger.v3.oas.integration.OpenApiContextLocator; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.stream.Collectors; import java.util.stream.Stream; import static io.swagger.v3.jaxrs2.integration.ServletConfigContextUtils.getContextIdFromServletConfig; public class BootstrapServlet extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { OpenAPI oas = new OpenAPI().openapi("3.0.1"); Info info = new Info() .title("Swagger Sample App - independent config exposed by dedicated servlet") .description("This is a sample server Petstore server. You can find out more about Swagger " + "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, " + "you can use the api key `special-key` to test the authorization filters.") .termsOfService("http://swagger.io/terms/") .contact(new Contact() .email("apiteam@swagger.io")) .license(new License() .name("Apache 2.0") .url("http://www.apache.org/licenses/LICENSE-2.0.html")); oas.info(info); SwaggerConfiguration oasConfig = new SwaggerConfiguration() .openAPI(oas) .prettyPrint(true) .openAPI31(true) .convertToOpenAPI31(true) .resourcePackages(Stream.of("io.swagger.v3.jaxrs2.it.resources").collect(Collectors.toSet())); try { new JaxrsOpenApiContextBuilder() .servletConfig(config) .openApiConfiguration(oasConfig) .buildContext(true); } catch (OpenApiConfigurationException e) { throw new ServletException(e.getMessage(), e); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String ctxId = getContextIdFromServletConfig(getServletConfig()); OpenApiContext ctx = OpenApiContextLocator.getInstance().getOpenApiContext(ctxId); OpenAPI oas = ctx.read(); resp.setStatus(200); resp.setContentType("application/yaml"); try (PrintWriter pw = resp.getWriter()) { pw.write(ctx.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(oas)); } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ContainerTypeSchemaTicket2636Test.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.testng.annotations.Test; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.HashMap; public class ContainerTypeSchemaTicket2636Test extends AbstractAnnotationTest { @Test public void testContainerTypeSchemaTicket2636() throws Exception { String expectedYaml = "openapi: 3.0.1\n" + "paths:\n" + " /path:\n" + " get:\n" + " summary: Op\n" + " description: 'RequestBody contains a Schema class that extends a Map '\n" + " operationId: getWithNoParameters\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/MyModel\"\n" + " required: true\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + "components:\n" + " schemas:\n" + " MyModel:\n" + " type: object\n" + " properties:\n" + " empty:\n" + " type: boolean\n" + " additionalProperties:\n" + " type: string"; compareAsYaml(RequestBodyInheritanceModelIssue.class, expectedYaml); } static class RequestBodyInheritanceModelIssue { @Operation( summary = "Op", description = "RequestBody contains a Schema class that extends a Map ", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet(@RequestBody(required=true, content = @Content(mediaType = "application/json", schema = @Schema(implementation = MyModel.class))) String data) { } } class MyModel extends HashMap { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/DecoratorExtensionTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.jaxrs2.ext.AbstractOpenAPIExtension; import io.swagger.v3.jaxrs2.ext.OpenAPIExtension; import io.swagger.v3.jaxrs2.ext.OpenAPIExtensions; import io.swagger.v3.jaxrs2.resources.SimpleResourceWithVendorAnnotation; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.responses.ApiResponse; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.lang.reflect.Method; import java.util.Iterator; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; public class DecoratorExtensionTest { private static final String RESPONSE_DESCRIPTION = "Some vendor error description"; private static final String RESPONSE_STATUS_401 = "401"; private static final OpenAPIExtension customExtension = new AbstractOpenAPIExtension() { @Override public void decorateOperation(final Operation operation, final Method method, final Iterator chain) { method.getDeclaredAnnotations(); final SimpleResourceWithVendorAnnotation.VendorFunnyAnnotation myFunyError = method.getAnnotation(SimpleResourceWithVendorAnnotation.VendorFunnyAnnotation.class); if (myFunyError != null) { /* * Extend swagger model by new error response description, with additional data received from vendor * based annotation. This example overwrite existing response from swagger annotation, but it is only * for demo. */ final ApiResponse value = new ApiResponse(); value.setDescription(RESPONSE_DESCRIPTION); operation.getResponses().put(RESPONSE_STATUS_401, value); } } }; private OpenAPI getOpenAPI(final Class cls) { return new Reader(new OpenAPI()).read(cls); } private Operation getGet(final OpenAPI swagger, final String path) { return swagger.getPaths().get(path).getGet(); } @BeforeMethod() public void addCustomExtension() { OpenAPIExtensions.getExtensions().add(customExtension); } @AfterMethod() public void removeCustomExtension() { OpenAPIExtensions.getExtensions().remove(customExtension); } /** * Test for method annotated with vendor annotation which could be used for swagger documentation. */ @Test(description = "scan a simple resource with custom decorator") public void scanSimpleResourceWithDecorator() { final OpenAPI openAPI = getOpenAPI(SimpleResourceWithVendorAnnotation.class); assertEquals(openAPI.getPaths().size(), 2); final Operation get = getGet(openAPI, "/{id}"); assertNotNull(get); assertEquals(get.getParameters().size(), 2); final ApiResponse response = get.getResponses().get(RESPONSE_STATUS_401); assertNotNull(response); assertEquals(response.getDescription(), RESPONSE_DESCRIPTION); } /** * Test for method annotated without vendor annotation. */ @Test(description = "scan a simple resource without custom decorator") public void scanSimpleResourceWithoutDecorator() { final OpenAPI openAPI = getOpenAPI(SimpleResourceWithVendorAnnotation.class); assertEquals(openAPI.getPaths().size(), 2); final Operation get = getGet(openAPI, "/{id}/value"); assertNotNull(get); final ApiResponse response = get.getResponses().get(RESPONSE_STATUS_401); assertNull(response); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/EnumTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; import io.swagger.v3.jaxrs2.resources.EnumParameterResource; import io.swagger.v3.oas.models.OpenAPI; import org.testng.annotations.Test; import java.io.IOException; public class EnumTest { @Test(description = "Test enum") public void testEnum() throws IOException { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(EnumParameterResource.class); SerializationMatchers.assertEqualsToYaml(openAPI, EXPECTED_YAML); } static final String EXPECTED_YAML = "openapi: 3.0.1\n" + "paths:\n" + " /task:\n" + " get:\n" + " operationId: getTasks\n" + " parameters:\n" + " - name: guid\n" + " in: query\n" + " required: true\n" + " schema:\n" + " type: string\n" + " - name: tasktype\n" + " in: query\n" + " schema:\n" + " type: string\n" + " enum:\n" + " - A\n" + " - B\n" + " responses:\n" + " \"200\":\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/TaskDTO\"\n" + " \"404\":\n" + " description: User not found\n" + "components:\n" + " schemas:\n" + " TaskDTO:\n" + " type: object\n"; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/FormParamBeanTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.jaxrs2.resources.model.FormParamBean; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.RequestBody; import org.testng.Assert; import org.testng.annotations.Test; import javax.ws.rs.*; import static org.testng.Assert.assertNotNull; public class FormParamBeanTest { @Path("/") private static class MyFormBeanParamResource { @GET @Consumes("application/x-www-form-urlencoded") public String getWithFormBeanParam(@BeanParam FormParamBean formParamBean) { return "result"; } } @Test(description = "check schema of serialized BeanParam containing FormParams") public void shouldSerializeTypeParameter() { OpenAPI openApi = new Reader(new OpenAPI()).read(MyFormBeanParamResource.class); RequestBody requestBody = openApi.getPaths().get("/").getGet().getRequestBody(); assertNotNull(requestBody); MediaType mediaType = requestBody.getContent().get("application/x-www-form-urlencoded"); assertNotNull(mediaType); Schema schema = mediaType.getSchema(); Assert.assertEquals(schema.getProperties().size(), 3); Assert.assertEquals(schema.getProperties().get("param1"), new StringSchema()); Assert.assertEquals(schema.getProperties().get("param2"), new StringSchema()); Assert.assertEquals(schema.getProperties().get("param3"), new StringSchema()); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/JaxbObjectMapperFactory.java ================================================ package io.swagger.v3.jaxrs2; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; import io.swagger.v3.core.util.ObjectMapperFactory; public class JaxbObjectMapperFactory extends ObjectMapperFactory { public static ObjectMapper getMapper() { ObjectMapper mapper = ObjectMapperFactory.createJson(); mapper.registerModule(new JaxbAnnotationModule()); return mapper; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/JsonIdentityTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; import io.swagger.v3.jaxrs2.resources.JsonIdentityCyclicResource; import io.swagger.v3.jaxrs2.resources.JsonIdentityResource; import io.swagger.v3.oas.models.OpenAPI; import org.testng.annotations.Test; import java.io.IOException; public class JsonIdentityTest { @Test(description = "Test JsonIdentity") public void testJsonIdentity() throws IOException { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(JsonIdentityResource.class); SerializationMatchers.assertEqualsToYaml(openAPI, EXPECTED_YAML); } @Test(description = "Test JsonIdentity Cyclic") public void testJsonIdentityCyclic() throws IOException { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(JsonIdentityCyclicResource.class); SerializationMatchers.assertEqualsToYaml(openAPI, EXPECTED_YAML_CYCLIC); } static final String EXPECTED_YAML_CYCLIC = "openapi: 3.0.1\n" + "paths:\n" + " /pet:\n" + " post:\n" + " description: Add a single object\n" + " operationId: test\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/ModelWithJsonIdentityCyclic\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n" + " application/xml: {}\n" + "components:\n" + " schemas:\n" + " SourceDefinition:\n" + " type: object\n" + " properties:\n" + " driver:\n" + " type: string\n" + " name:\n" + " type: string\n" + " model:\n" + " type: integer\n" + " format: int64\n" + " ModelWithJsonIdentityCyclic:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " sourceDefinitions:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/SourceDefinition\"\n"; static final String EXPECTED_YAML = "openapi: 3.0.1\n" + "paths:\n" + " /pet:\n" + " post:\n" + " description: Add a single object\n" + " operationId: test\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/ModelWithJsonIdentity\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n" + " application/xml: {}\n" + "components:\n" + " schemas:\n" + " ModelWithJsonIdentity:\n" + " type: object\n" + " properties:\n" + " PropertyGeneratorAsId:\n" + " type: string\n" + " PropertyGeneratorAsProperty:\n" + " $ref: \"#/components/schemas/SourceDefinition1\"\n" + " ChangedPropertyName:\n" + " type: string\n" + " ChangedPropertyName2:\n" + " type: string\n" + " SourceWithoutPropertyAsId:\n" + " type: string\n" + " SourceWithoutPropertyAsProperty:\n" + " $ref: \"#/components/schemas/SourceDefinition3\"\n" + " IntSequenceGeneratorAsId:\n" + " type: integer\n" + " format: int32\n" + " IntSequenceGeneratorAsProperty:\n" + " $ref: \"#/components/schemas/SourceDefinition4\"\n" + " IntSequenceWithoutPropertyAsId:\n" + " type: integer\n" + " format: int32\n" + " IntSequenceWithoutPropertyAsProperty:\n" + " $ref: \"#/components/schemas/SourceDefinition5\"\n" + " UUIDGeneratorAsId:\n" + " type: string\n" + " format: uuid\n" + " UUIDGeneratorAsProperty:\n" + " $ref: \"#/components/schemas/SourceDefinition6\"\n" + " UUIDGeneratorWithoutPropertyAsId:\n" + " type: string\n" + " format: uuid\n" + " UUIDGeneratorWithoutPropertyAsProperty:\n" + " $ref: \"#/components/schemas/SourceDefinition7\"\n" + " GeneratorsNone:\n" + " $ref: \"#/components/schemas/SourceDefinition8\"\n" + " CustomGenerator:\n" + " type: string\n" + " WithoutJsonIdentityReference:\n" + " $ref: \"#/components/schemas/SourceDefinition10\"\n" + " IntSequenceGeneratorAtClassLevel:\n" + " $ref: \"#/components/schemas/SourceDefinition11\"\n" + " SourceDefinition1:\n" + " type: object\n" + " properties:\n" + " driver:\n" + " type: string\n" + " name:\n" + " type: string\n" + " SourceDefinition10:\n" + " type: object\n" + " properties:\n" + " driver:\n" + " type: string\n" + " name:\n" + " type: string\n" + " SourceDefinition11:\n" + " type: object\n" + " properties:\n" + " 'name':\n" + " type: string\n" + " '@id':\n" + " type: integer\n" + " format: int32\n"+ " SourceDefinition3:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " driverId:\n" + " type: string\n" + " '@id':\n" + " type: string\n" + " SourceDefinition4:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " testName2:\n" + " type: integer\n" + " format: int32\n" + " SourceDefinition5:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " '@id':\n" + " type: integer\n" + " format: int32\n" + " SourceDefinition6:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " UUID2:\n" + " type: string\n" + " format: uuid\n" + " SourceDefinition7:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " '@id':\n" + " type: string\n" + " format: uuid\n" + " SourceDefinition8:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " driverId:\n" + " type: string\n"; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/JsonViewTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.media.MediaType; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.core.JsonProcessingException; import java.util.Arrays; import java.util.List; import java.util.Set; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.core.Response; import org.testng.annotations.Test; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; public class JsonViewTest { private static class View { interface Summary { } interface Detail extends Summary { } interface Sale { } } private static class Car { @JsonView(View.Summary.class) @JsonProperty("manufacture") private String made = "Honda"; @JsonView({View.Summary.class, View.Detail.class}) private String model = "Accord Hybrid"; @JsonView({View.Detail.class}) @JsonProperty private List tires = Arrays.asList(new Tire()); @JsonView({View.Sale.class}) @JsonProperty private int price = 40000; // always in private String color = "White"; public String getColor() { return color; } } private static class Tire { @JsonView(View.Summary.class) @JsonProperty("brand") private String made = "Michelin"; @JsonView(View.Detail.class) @JsonProperty private String condition = "new"; } @Path("/") private static class CarSummaryApi { @GET @Path("/cars/summary") @JsonView({View.Summary.class}) public List getSummaries() { return Arrays.asList(new Car()); } } @Path("/") private static class CarSummaryUpdateApi { @PUT @Path("/cars/summary") @Operation(description = "Updates a car summary.") public Response updateCarSummary( @RequestBody(content = @Content(schema = @Schema(implementation = Car.class))) @JsonView(View.Summary.class) Car car) { return Response.noContent() .build(); } } @Path("/") private static class CarDetailApi { @GET @Path("/cars/detail") @JsonView({View.Detail.class}) @Operation(description = "Return car detail", responses = @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema (implementation = Car.class))))) public Response getDetails() { return Response.ok(Arrays.asList(new Car())).build(); } } @Path("/") private static class CarSaleSummaryApi { @GET @Path("/cars/sale") @JsonView({View.Summary.class, View.Sale.class}) public List getSaleSummaries() { return Arrays.asList(new Car()); } } @Path("/") private static class CarApi { @GET @Path("/cars") public List getCars() { return Arrays.asList(new Car()); } } @Path("/ignore") private static class CarIgnoreApi { @GET @Path("/cars") @JsonView({View.Summary.class, View.Sale.class}) @Operation(ignoreJsonView = true) public List getCars() { return Arrays.asList(new Car()); } } @Test(description = "check awareness of JsonView") public void shouldSerializeTypeParameter() throws JsonProcessingException { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(CarSummaryApi.class); String openApiJson = Json.mapper().writeValueAsString(openAPI); assertTrue(openApiJson.contains("manufacture")); assertTrue(openApiJson.contains("model")); assertTrue(openApiJson.contains("color")); assertFalse(openApiJson.contains("tires")); assertFalse(openApiJson.contains("made")); assertFalse(openApiJson.contains("condition")); reader = new Reader(new OpenAPI()); openAPI = reader.read(CarSummaryUpdateApi.class); Set carSummarySchemaProperties = openAPI.getComponents() .getSchemas() .get("Car_Summary") .getProperties() .keySet(); String carSummaryUpdateApiRequestBodySchemaRef = openAPI.getPaths() .values() .stream() .findAny() .orElse(new PathItem()) .getPut() .getRequestBody() .getContent() .values() .stream() .findAny() .orElse(new MediaType()) .getSchema() .get$ref(); assertTrue(carSummarySchemaProperties.contains("manufacture")); assertTrue(carSummarySchemaProperties.contains("model")); assertTrue(carSummarySchemaProperties.contains("color")); assertFalse(carSummarySchemaProperties.contains("price")); assertFalse(carSummarySchemaProperties.contains("tires")); assertFalse(carSummarySchemaProperties.contains("made")); assertFalse(carSummarySchemaProperties.contains("condition")); assertTrue(carSummaryUpdateApiRequestBodySchemaRef.contains("Car_Summary")); reader = new Reader(new OpenAPI()); openAPI = reader.read(CarDetailApi.class); openApiJson = Json.mapper().writeValueAsString(openAPI); assertTrue(openApiJson.contains("manufacture")); assertTrue(openApiJson.contains("model")); assertTrue(openApiJson.contains("color")); assertTrue(openApiJson.contains("tires")); assertTrue(openApiJson.contains("brand")); assertTrue(openApiJson.contains("condition")); assertTrue(openApiJson.contains("Car_Detail")); reader = new Reader(new OpenAPI()); openAPI = reader.read(CarSaleSummaryApi.class); openApiJson = Json.mapper().writeValueAsString(openAPI); Yaml.prettyPrint(openAPI); assertTrue(openApiJson.contains("manufacture")); assertTrue(openApiJson.contains("model")); assertTrue(openApiJson.contains("color")); assertTrue(openApiJson.contains("price")); assertFalse(openApiJson.contains("tires")); assertFalse(openApiJson.contains("made")); assertFalse(openApiJson.contains("condition")); reader = new Reader(new OpenAPI()); openAPI = reader.read(CarApi.class); openApiJson = Json.mapper().writeValueAsString(openAPI); assertTrue(openApiJson.contains("manufacture")); assertTrue(openApiJson.contains("model")); assertTrue(openApiJson.contains("color")); assertTrue(openApiJson.contains("price")); assertTrue(openApiJson.contains("tires")); assertFalse(openApiJson.contains("made")); assertTrue(openApiJson.contains("condition")); reader = new Reader(new OpenAPI()); openAPI = reader.read(CarIgnoreApi.class); openApiJson = Json.mapper().writeValueAsString(openAPI); assertTrue(openApiJson.contains("manufacture")); assertTrue(openApiJson.contains("model")); assertTrue(openApiJson.contains("color")); assertTrue(openApiJson.contains("price")); assertTrue(openApiJson.contains("tires")); assertFalse(openApiJson.contains("made")); assertTrue(openApiJson.contains("condition")); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/PetResourceTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; import io.swagger.v3.jaxrs2.petstore.EmptyPetResource; import io.swagger.v3.jaxrs2.petstore.WebHookResource; import io.swagger.v3.jaxrs2.petstore.callback.ComplexCallback31Resource; import io.swagger.v3.jaxrs2.petstore.callback.ComplexCallbackResource; import io.swagger.v3.jaxrs2.petstore.callback.MultipleCallbacksTestWithOperationResource; import io.swagger.v3.jaxrs2.petstore.callback.RepeatableCallbackResource; import io.swagger.v3.jaxrs2.petstore.callback.SimpleCallbackWithOperationResource; import io.swagger.v3.jaxrs2.petstore.example.ExamplesResource; import io.swagger.v3.jaxrs2.petstore.link.LinksAndContent31Resource; import io.swagger.v3.jaxrs2.petstore.link.LinksResource; import io.swagger.v3.jaxrs2.petstore.openapidefintion.OpenAPI31DefinitionResource; import io.swagger.v3.jaxrs2.petstore.openapidefintion.OpenAPIDefinitionResource; import io.swagger.v3.jaxrs2.petstore.operation.AnnotatedSameNameOperationResource; import io.swagger.v3.jaxrs2.petstore.operation.ExternalDocumentationResource; import io.swagger.v3.jaxrs2.petstore.operation.FullyAnnotatedOperationResource; import io.swagger.v3.jaxrs2.petstore.operation.HiddenOperationResource; import io.swagger.v3.jaxrs2.petstore.operation.NotAnnotatedSameNameOperationResource; import io.swagger.v3.jaxrs2.petstore.operation.OperationResource; import io.swagger.v3.jaxrs2.petstore.operation.OperationWithoutAnnotationResource; import io.swagger.v3.jaxrs2.petstore.operation.ServerOperationResource; import io.swagger.v3.jaxrs2.petstore.operation.SubResource; import io.swagger.v3.jaxrs2.petstore.parameter.ArraySchemaResource; import io.swagger.v3.jaxrs2.petstore.parameter.ComplexParameterResource; import io.swagger.v3.jaxrs2.petstore.parameter.ComplexParameterWithOperationResource; import io.swagger.v3.jaxrs2.petstore.parameter.MultipleNotAnnotatedParameter; import io.swagger.v3.jaxrs2.petstore.parameter.OpenAPIJaxRSAnnotatedParameter; import io.swagger.v3.jaxrs2.petstore.parameter.OpenAPIWithContentJaxRSAnnotatedParameter; import io.swagger.v3.jaxrs2.petstore.parameter.OpenAPIWithImplementationJaxRSAnnotatedParameter; import io.swagger.v3.jaxrs2.petstore.parameter.Parameters31Resource; import io.swagger.v3.jaxrs2.petstore.parameter.ParametersResource; import io.swagger.v3.jaxrs2.petstore.parameter.RepeatableParametersResource; import io.swagger.v3.jaxrs2.petstore.parameter.SingleJaxRSAnnotatedParameter; import io.swagger.v3.jaxrs2.petstore.parameter.SingleNotAnnotatedParameter; import io.swagger.v3.jaxrs2.petstore.requestbody.RequestBody31Resource; import io.swagger.v3.jaxrs2.petstore.requestbody.RequestBodyMethodPriorityResource; import io.swagger.v3.jaxrs2.petstore.requestbody.RequestBodyParameterPriorityResource; import io.swagger.v3.jaxrs2.petstore.requestbody.RequestBodyResource; import io.swagger.v3.jaxrs2.petstore.responses.*; import io.swagger.v3.jaxrs2.petstore.security.SecurityResource; import io.swagger.v3.jaxrs2.petstore.tags.CompleteTagResource; import io.swagger.v3.jaxrs2.petstore.tags.TagClassResource; import io.swagger.v3.jaxrs2.petstore.tags.TagMethodResource; import io.swagger.v3.jaxrs2.petstore.tags.TagOpenAPIDefinitionResource; import io.swagger.v3.jaxrs2.petstore.tags.TagOperationResource; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.OpenAPI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; /** * Pet Resource Test Class * Adding a lot of tests of different pet resource examples */ public class PetResourceTest extends AbstractAnnotationTest { private static final Logger LOGGER = LoggerFactory.getLogger(PetResourceTest.class); private static final String PETSTORE_SOURCE = "petstore/"; private static final String TAGS_SOURCE = "petstore/tags/"; private static final String OPERATIONS_SOURCE = "petstore/operation/"; private static final String CALLBACKS_SOURCE = "petstore/callbacks/"; private static final String RESPONSES_SOURCE = "petstore/responses/"; private static final String PARAMETERS_SOURCE = "petstore/parameters/"; private static final String LINKS_SOURCE = "petstore/links/"; private static final String EXAMPLES_SOURCE = "petstore/example/"; private static final String REQUEST_BODIES_SOURCE = "petstore/requestbody/"; private static final String YAML_EXTENSION = ".yaml"; private static final String PETSTORE_PACKAGE = "io.swagger.v3.jaxrs2.petstore"; private static final char DOT = '.'; private static final char SLASH = '/'; @Test(description = "Test an empty resource class (Without operations or annotations)") public void testEmptyPetResource() { compare(EmptyPetResource.class, PETSTORE_SOURCE); } @Test(description = "Test a resource with examples)") public void testExamplesResource() { compare(ExamplesResource.class, EXAMPLES_SOURCE); } @Test(description = "Test a resource with Links)") public void testLinksResource() { compare(LinksResource.class, LINKS_SOURCE); } @Test(description = "Test some resources with Callbacks)") public void testCallBacksResources() { compare(SimpleCallbackWithOperationResource.class, CALLBACKS_SOURCE); compare(MultipleCallbacksTestWithOperationResource.class, CALLBACKS_SOURCE); compare(RepeatableCallbackResource.class, CALLBACKS_SOURCE); compare(ComplexCallbackResource.class, CALLBACKS_SOURCE); } @Test(description = "Test some resources with different Operations scenarios)") public void testOperationsResources() { compare(HiddenOperationResource.class, OPERATIONS_SOURCE); compare(OperationWithoutAnnotationResource.class, OPERATIONS_SOURCE); compare(FullyAnnotatedOperationResource.class, OPERATIONS_SOURCE); compare(AnnotatedSameNameOperationResource.class, OPERATIONS_SOURCE); compare(NotAnnotatedSameNameOperationResource.class, OPERATIONS_SOURCE); compare(ExternalDocumentationResource.class, OPERATIONS_SOURCE); compare(ServerOperationResource.class, OPERATIONS_SOURCE); compare(SubResource.class, OPERATIONS_SOURCE); compare(OperationResource.class, OPERATIONS_SOURCE); } @Test(description = "Test OpenAPIDefinition resource)") public void testOpenAPIDefinitionResource() { compare(OpenAPIDefinitionResource.class, PETSTORE_SOURCE); } @Test(description = "Test RequestBody resource)") public void tetRequestBodyResource() { compare(RequestBodyResource.class, REQUEST_BODIES_SOURCE); compare(RequestBodyParameterPriorityResource.class, REQUEST_BODIES_SOURCE); compare(RequestBodyMethodPriorityResource.class, REQUEST_BODIES_SOURCE); } @Test(description = "Test Parameters resources)") public void testParametersResource() { compare(ParametersResource.class, PARAMETERS_SOURCE); compare(RepeatableParametersResource.class, PARAMETERS_SOURCE); compare(ArraySchemaResource.class, PARAMETERS_SOURCE); compare(SingleNotAnnotatedParameter.class, PARAMETERS_SOURCE); compare(MultipleNotAnnotatedParameter.class, PARAMETERS_SOURCE); compare(SingleJaxRSAnnotatedParameter.class, PARAMETERS_SOURCE); compare(OpenAPIJaxRSAnnotatedParameter.class, PARAMETERS_SOURCE); compare(OpenAPIWithContentJaxRSAnnotatedParameter.class, PARAMETERS_SOURCE); compare(OpenAPIWithImplementationJaxRSAnnotatedParameter.class, PARAMETERS_SOURCE); compare(ComplexParameterResource.class, PARAMETERS_SOURCE); compare(ComplexParameterWithOperationResource.class, PARAMETERS_SOURCE); } @Test(description = "Test ApiResponses resource)") public void testResponsesResource() { compare(MethodResponseResource.class, RESPONSES_SOURCE); compare(OperationResponseResource.class, RESPONSES_SOURCE); compare(NoResponseResource.class, RESPONSES_SOURCE); compare(ImplementationResponseResource.class, RESPONSES_SOURCE); compare(NoImplementationResponseResource.class, RESPONSES_SOURCE); compare(PriorityResponseResource.class, RESPONSES_SOURCE); compare(ComplexResponseResource.class, RESPONSES_SOURCE); } @Test(description = "Test Security resource)") public void testSecurityResource() { compare(SecurityResource.class, PETSTORE_SOURCE); } @Test(description = "Test Tags resource)") public void testTagsResource() { compare(CompleteTagResource.class, TAGS_SOURCE); compare(TagOpenAPIDefinitionResource.class, TAGS_SOURCE); compare(TagClassResource.class, TAGS_SOURCE); compare(TagMethodResource.class, TAGS_SOURCE); compare(TagOperationResource.class, TAGS_SOURCE); } @Test(description = "Test a full set of classes") public void testSetOfClasses() { final Reader reader = new Reader(new OpenAPI()); final OpenAPI openAPI = reader.read(getSetOfClassesFromPackage(PETSTORE_PACKAGE)); assertNotNull(openAPI); try { SerializationMatchers.assertEqualsToYaml(openAPI, getOpenAPIAsString(PETSTORE_SOURCE + "FullPetResource.yaml")); } catch (IOException e) { fail(); } } /** * Extract a set of classes from a package name * * @param packageName target to scan the classes * @return Set */ private Set> getSetOfClassesFromPackage(final String packageName) { final Set> classSet = new HashSet<>(); try { final Class[] classes = getClasses(packageName); for (final Class aClass : classes) { classSet.add(aClass); } } catch (final ClassNotFoundException | IOException e) { fail(); } return classSet; } /** * Scans all classes accessible from the context class loader which belong to the given package and subpackages. * * @param packageName The base package * @return The classes */ private static Class[] getClasses(final String packageName) throws ClassNotFoundException, IOException { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); assert classLoader != null; final String path = packageName.replace(DOT, SLASH); final Enumeration resources = classLoader.getResources(path); final List dirs = new ArrayList<>(); while (resources.hasMoreElements()) { final URL resource = resources.nextElement(); dirs.add(new File(resource.getFile())); } final ArrayList classes = new ArrayList<>(); for (final File directory : dirs) { classes.addAll(findClasses(directory, packageName)); } return classes.toArray(new Class[classes.size()]); } /** * Recursive method used to find all classes in a given directory and subdirectories. * * @param directory The base directory * @param packageName The package name for classes found inside the base directory * @return The classes */ private static List findClasses(final File directory, final String packageName) throws ClassNotFoundException { final List classes = new ArrayList<>(); if (!directory.exists()) { return classes; } final File[] files = directory.listFiles(); if (files != null) { for (final File file : files) { if (file.isDirectory()) { assert !file.getName().contains("."); classes.addAll(findClasses(file, packageName + "." + file.getName())); } else if (file.getName().endsWith(".class")) { classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6))); } } } return classes; } @Test(description = "Test an empty resource class (Without operations or annotations)") public void testEmptyPet31Resource() { Reader reader = new Reader(new SwaggerConfiguration() .openAPI(new OpenAPI()) .openAPI31(true)); OpenAPI openAPI = reader.read(Object.class); SerializationMatchers.assertEqualsToYaml31(openAPI, "openapi: 3.1.0"); } @Test(description = "Test a resource with Links and Content)") public void testLinksAndContent31Resource() { compare(LinksAndContent31Resource.class, LINKS_SOURCE, true); } @Test(description = "Test OpenAPIDefinition resource)") public void testOpenAPI31DefinitionResource() { compare(OpenAPI31DefinitionResource.class, PETSTORE_SOURCE, true); } @Test(description = "Test Parameters resources)") public void testParameters31Resource() { compare(Parameters31Resource.class, PARAMETERS_SOURCE, true); } @Test(description = "Test some resources with Callbacks)") public void testCallBacks31Resources() { compare(ComplexCallback31Resource.class, CALLBACKS_SOURCE, true); } @Test(description = "Test some resources with Request Body)") public void testRequestBody31Resources() { compare(RequestBody31Resource.class, REQUEST_BODIES_SOURCE, true); } @Test(description = "Test webhook resources") public void testWebhooksResource() { compare(WebHookResource.class, PETSTORE_SOURCE, true); } @Test(description = "Test method resources with array annotations") public void testMethodArrayResponseResource() { compare(MethodArrayResponseResource.class, RESPONSES_SOURCE, true); } /** * Compare a class that were read and parsed to a yaml against a yaml file. * * @param clazz to read. * @param source where is the yaml. */ private void compare(final Class clazz, final String source) { compare(clazz, source, false); } private void compare(final Class clazz, final String source, boolean openapi31) { final String file = source + clazz.getSimpleName() + YAML_EXTENSION; try { if (openapi31) { compareAsYamlOAS31(clazz, getOpenAPIAsString(file)); } else { compareAsYaml(clazz, getOpenAPIAsString(file)); } } catch (IOException e) { LOGGER.error("Failed to compare class {} with YAML resource {}", clazz.getName(), file, e); fail(); } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java ================================================ package io.swagger.v3.jaxrs2; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContextImpl; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ResolvedSchema; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.filter.OpenAPISpecFilter; import io.swagger.v3.core.filter.SpecFilter; import io.swagger.v3.core.jackson.ModelResolver; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.PrimitiveType; import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; import io.swagger.v3.jaxrs2.petstore31.PetResource; import io.swagger.v3.jaxrs2.petstore31.TagResource; import io.swagger.v3.jaxrs2.resources.ArraySchemaImplementationResource; import io.swagger.v3.jaxrs2.resources.DefaultResponseResource; import io.swagger.v3.jaxrs2.resources.Misc31Resource; import io.swagger.v3.jaxrs2.resources.ParameterMaximumValueResource; import io.swagger.v3.jaxrs2.resources.ResponseReturnTypeResource; import io.swagger.v3.jaxrs2.resources.SchemaAdditionalPropertiesBooleanResource; import io.swagger.v3.jaxrs2.resources.SchemaAdditionalPropertiesResource; import io.swagger.v3.jaxrs2.resources.SchemaPropertiesResource; import io.swagger.v3.jaxrs2.resources.SiblingPropResource; import io.swagger.v3.jaxrs2.resources.SiblingsResource; import io.swagger.v3.jaxrs2.resources.SiblingsResourceRequestBody; import io.swagger.v3.jaxrs2.resources.SiblingsResourceRequestBodyMultiple; import io.swagger.v3.jaxrs2.resources.SiblingsResourceResponse; import io.swagger.v3.jaxrs2.resources.SiblingsResourceSimple; import io.swagger.v3.jaxrs2.resources.SingleExampleResource; import io.swagger.v3.jaxrs2.resources.BasicFieldsResource; import io.swagger.v3.jaxrs2.resources.BookStoreTicket2646; import io.swagger.v3.jaxrs2.resources.ClassPathParentResource; import io.swagger.v3.jaxrs2.resources.ClassPathSubResource; import io.swagger.v3.jaxrs2.resources.CompleteFieldsResource; import io.swagger.v3.jaxrs2.resources.DeprecatedFieldsResource; import io.swagger.v3.jaxrs2.resources.DuplicatedOperationIdResource; import io.swagger.v3.jaxrs2.resources.DuplicatedOperationMethodNameResource; import io.swagger.v3.jaxrs2.resources.DuplicatedSecurityResource; import io.swagger.v3.jaxrs2.resources.EnhancedResponsesResource; import io.swagger.v3.jaxrs2.resources.ExternalDocsReference; import io.swagger.v3.jaxrs2.resources.MyClass; import io.swagger.v3.jaxrs2.resources.MyOtherClass; import io.swagger.v3.jaxrs2.resources.RefCallbackResource; import io.swagger.v3.jaxrs2.resources.RefExamplesResource; import io.swagger.v3.jaxrs2.resources.RefHeaderResource; import io.swagger.v3.jaxrs2.resources.RefLinksResource; import io.swagger.v3.jaxrs2.resources.RefParameter3029Resource; import io.swagger.v3.jaxrs2.resources.RefParameter3074Resource; import io.swagger.v3.jaxrs2.resources.RefParameterResource; import io.swagger.v3.jaxrs2.resources.RefRequestBodyResource; import io.swagger.v3.jaxrs2.resources.RefResponsesResource; import io.swagger.v3.jaxrs2.resources.RefSecurityResource; import io.swagger.v3.jaxrs2.resources.ResourceWithSubResource; import io.swagger.v3.jaxrs2.resources.ResponseContentWithArrayResource; import io.swagger.v3.jaxrs2.resources.ResponsesResource; import io.swagger.v3.jaxrs2.resources.SecurityResource; import io.swagger.v3.jaxrs2.resources.ServersResource; import io.swagger.v3.jaxrs2.resources.SimpleCallbackResource; import io.swagger.v3.jaxrs2.resources.SimpleExamplesResource; import io.swagger.v3.jaxrs2.resources.SimpleMethods; import io.swagger.v3.jaxrs2.resources.SimpleParameterResource; import io.swagger.v3.jaxrs2.resources.SimpleRequestBodyResource; import io.swagger.v3.jaxrs2.resources.SimpleResponsesResource; import io.swagger.v3.jaxrs2.resources.SubResourceHead; import io.swagger.v3.jaxrs2.resources.TagsResource; import io.swagger.v3.jaxrs2.resources.Test2607; import io.swagger.v3.jaxrs2.resources.TestResource; import io.swagger.v3.jaxrs2.resources.Ticket2340Resource; import io.swagger.v3.jaxrs2.resources.Ticket2644ConcreteImplementation; import io.swagger.v3.jaxrs2.resources.Ticket2763Resource; import io.swagger.v3.jaxrs2.resources.Ticket2793Resource; import io.swagger.v3.jaxrs2.resources.Ticket2794Resource; import io.swagger.v3.jaxrs2.resources.Ticket2806Resource; import io.swagger.v3.jaxrs2.resources.Ticket2818Resource; import io.swagger.v3.jaxrs2.resources.Ticket2848Resource; import io.swagger.v3.jaxrs2.resources.Ticket3015Resource; import io.swagger.v3.jaxrs2.resources.Ticket3587Resource; import io.swagger.v3.jaxrs2.resources.Ticket3731BisResource; import io.swagger.v3.jaxrs2.resources.Ticket3731Resource; import io.swagger.v3.jaxrs2.resources.Ticket4065Resource; import io.swagger.v3.jaxrs2.resources.Ticket4341Resource; import io.swagger.v3.jaxrs2.resources.Ticket4412Resource; import io.swagger.v3.jaxrs2.resources.Ticket4446Resource; import io.swagger.v3.jaxrs2.resources.Ticket4483Resource; import io.swagger.v3.jaxrs2.resources.Ticket4804CustomClass; import io.swagger.v3.jaxrs2.resources.Ticket4804NotBlankResource; import io.swagger.v3.jaxrs2.resources.Ticket4804ProcessorResource; import io.swagger.v3.jaxrs2.resources.Ticket4804Resource; import io.swagger.v3.jaxrs2.resources.Ticket4850Resource; import io.swagger.v3.jaxrs2.resources.Ticket4859Resource; import io.swagger.v3.jaxrs2.resources.Ticket4878Resource; import io.swagger.v3.jaxrs2.resources.Ticket4879Resource; import io.swagger.v3.jaxrs2.resources.Ticket5017Resource; import io.swagger.v3.jaxrs2.resources.UploadResource; import io.swagger.v3.jaxrs2.resources.UrlEncodedResourceWithEncodings; import io.swagger.v3.jaxrs2.resources.UserAnnotationResource; import io.swagger.v3.jaxrs2.resources.WebHookResource; import io.swagger.v3.jaxrs2.resources.extensions.ExtensionsResource; import io.swagger.v3.jaxrs2.resources.extensions.OperationExtensionsResource; import io.swagger.v3.jaxrs2.resources.extensions.ParameterExtensionsResource; import io.swagger.v3.jaxrs2.resources.extensions.RequestBodyExtensionsResource; import io.swagger.v3.jaxrs2.resources.generics.ticket2144.ItemResource; import io.swagger.v3.jaxrs2.resources.generics.ticket3149.MainResource; import io.swagger.v3.jaxrs2.resources.generics.ticket3426.Ticket3426Resource; import io.swagger.v3.jaxrs2.resources.generics.ticket3694.Ticket3694Resource; import io.swagger.v3.jaxrs2.resources.generics.ticket3694.Ticket3694ResourceExtendedType; import io.swagger.v3.jaxrs2.resources.generics.ticket3694.Ticket3694ResourceSimple; import io.swagger.v3.jaxrs2.resources.generics.ticket3694.Ticket3694ResourceSimpleSameReturn; import io.swagger.v3.jaxrs2.resources.rs.ProcessTokenRestService; import io.swagger.v3.jaxrs2.resources.ticket3624.Service; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.ExternalDocumentation; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import org.testng.annotations.Test; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.OPTIONS; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.net.URI; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; /** * Test for the Reader Class */ public class ReaderTest { private static final String EXAMPLE_TAG = "Example Tag"; private static final String SECOND_TAG = "Second Tag"; private static final String OPERATION_SUMMARY = "Operation Summary"; private static final String OPERATION_DESCRIPTION = "Operation Description"; private static final String CALLBACK_POST_OPERATION_DESCRIPTION = "payload data will be sent"; private static final String CALLBACK_GET_OPERATION_DESCRIPTION = "payload data will be received"; private static final String RESPONSE_CODE_200 = "200"; private static final String RESPONSE_DESCRIPTION = "voila!"; private static final String EXTERNAL_DOCS_DESCRIPTION = "External documentation description"; private static final String EXTERNAL_DOCS_URL = "http://url.com"; private static final String PARAMETER_IN = "path"; private static final String PARAMETER_NAME = "subscriptionId"; private static final String PARAMETER_DESCRIPTION = "parameter description"; private static final String CALLBACK_SUBSCRIPTION_ID = "subscription"; private static final String CALLBACK_URL = "http://$request.query.url"; private static final String SECURITY_KEY = "security_key"; private static final String SCOPE_VALUE1 = "write:pets"; private static final String SCOPE_VALUE2 = "read:pets"; private static final String PATH_REF = "/"; private static final String PATH_1_REF = "/1"; private static final String PATH_2_REF = "/path"; private static final String SCHEMA_TYPE = "string"; private static final String SCHEMA_FORMAT = "uuid"; private static final String SCHEMA_DESCRIPTION = "the generated UUID"; private static final int RESPONSES_NUMBER = 2; private static final int TAG_NUMBER = 2; private static final int SECURITY_SCHEMAS = 2; private static final int PARAMETER_NUMBER = 1; private static final int SECURITY_REQUIREMENT_NUMBER = 1; private static final int SCOPE_NUMBER = 2; private static final int PATHS_NUMBER = 1; @Test(description = "test a simple resource class") public void testSimpleReadClass() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(BasicFieldsResource.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 6); PathItem pathItem = paths.get(PATH_1_REF); assertNotNull(pathItem); assertNull(pathItem.getPost()); Operation operation = pathItem.getGet(); assertNotNull(operation); assertEquals(OPERATION_SUMMARY, operation.getSummary()); assertEquals(OPERATION_DESCRIPTION, operation.getDescription()); } @Test(description = "scan methods") public void testCompleteReadClass() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(CompleteFieldsResource.class); Paths paths = openAPI.getPaths(); assertEquals(PATHS_NUMBER, paths.size()); PathItem pathItem = paths.get(PATH_REF); assertNotNull(pathItem); assertNull(pathItem.getPost()); Operation operation = pathItem.getGet(); assertNotNull(operation); assertEquals(OPERATION_SUMMARY, operation.getSummary()); assertEquals(OPERATION_DESCRIPTION, operation.getDescription()); assertEquals(TAG_NUMBER, operation.getTags().size()); assertEquals(EXAMPLE_TAG, operation.getTags().get(0)); assertEquals(SECOND_TAG, operation.getTags().get(1)); ExternalDocumentation externalDocs = operation.getExternalDocs(); assertEquals(EXTERNAL_DOCS_DESCRIPTION, externalDocs.getDescription()); assertEquals(EXTERNAL_DOCS_URL, externalDocs.getUrl()); } @Test(description = "scan methods") public void testScanMethods() { Reader reader = new Reader(new OpenAPI()); Method[] methods = SimpleMethods.class.getMethods(); for (final Method method : methods) { if (isValidRestPath(method)) { Operation operation = reader.parseMethod(method, null, null); assertNotNull(operation); } } } @Test(description = "Get a Summary and Description") public void testGetSummaryAndDescription() { Reader reader = new Reader(new OpenAPI()); Method[] methods = BasicFieldsResource.class.getMethods(); Operation operation = reader.parseMethod(methods[0], null, null); assertNotNull(operation); assertEquals(OPERATION_SUMMARY, operation.getSummary()); assertEquals(OPERATION_DESCRIPTION, operation.getDescription()); } @Test(description = "Get a Duplicated Operation Id") public void testResolveDuplicatedOperationId() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(DuplicatedOperationIdResource.class); Paths paths = openAPI.getPaths(); assertNotNull(paths); Operation firstOperation = paths.get(PATH_REF).getGet(); Operation secondOperation = paths.get(PATH_2_REF).getGet(); Operation thirdOperation = paths.get(PATH_REF).getPost(); assertNotNull(firstOperation); assertNotNull(secondOperation); assertNotNull(thirdOperation); assertNotEquals(firstOperation.getOperationId(), secondOperation.getOperationId()); assertNotEquals(firstOperation.getOperationId(), thirdOperation.getOperationId()); assertNotEquals(secondOperation.getOperationId(), thirdOperation.getOperationId()); } @Test(description = "Get a Duplicated Operation Id with same id as method name") public void testResolveDuplicatedOperationIdMethodName() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(DuplicatedOperationMethodNameResource.class); Paths paths = openAPI.getPaths(); assertNotNull(paths); Operation firstOperation = paths.get("/1").getGet(); Operation secondOperation = paths.get("/2").getGet(); Operation secondPostOperation = paths.get("/2").getPost(); Operation thirdPostOperation = paths.get("/3").getPost(); assertNotNull(firstOperation); assertNotNull(secondOperation); assertNotNull(secondPostOperation); assertNotNull(thirdPostOperation); assertNotEquals(firstOperation.getOperationId(), secondOperation.getOperationId()); assertNotEquals(secondOperation.getOperationId(), secondPostOperation.getOperationId()); assertNotEquals(secondPostOperation.getOperationId(), thirdPostOperation.getOperationId()); Operation thirdOperation = paths.get("/3").getGet(); Operation fourthOperation = paths.get("/4").getGet(); assertNotNull(thirdOperation); assertNotNull(fourthOperation); assertNotEquals(thirdOperation.getOperationId(), fourthOperation.getOperationId()); } @Test(description = "Test a Set of classes") public void testSetOfClasses() { Set> classes = new HashSet<>(); classes.add(SecurityResource.class); classes.add(DuplicatedSecurityResource.class); Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(classes); assertNotNull(openAPI); assertEquals(openAPI.getPaths().get("/").getGet().getSecurity().size(), 2); assertEquals(openAPI.getPaths().get("/2").getGet().getSecurity().size(), 3); Components components = openAPI.getComponents(); assertNotNull(components); Map securitySchemes = components.getSecuritySchemes(); assertNotNull(securitySchemes); assertEquals(SECURITY_SCHEMAS, securitySchemes.size()); } @Test(description = "Deprecated Method") public void testDeprecatedMethod() { Reader reader = new Reader(new OpenAPI()); Method[] methods = DeprecatedFieldsResource.class.getMethods(); Operation deprecatedOperation = reader.parseMethod(methods[0], null, null); assertNotNull(deprecatedOperation); assertTrue(deprecatedOperation.getDeprecated()); } @Test(description = "Get tags") public void testGetTags() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(TagsResource.class); Operation operation = openAPI.getPaths().get("/").getGet(); assertNotNull(operation); assertEquals(6, operation.getTags().size()); assertEquals(operation.getTags().get(3), EXAMPLE_TAG); assertEquals(operation.getTags().get(1), SECOND_TAG); assertEquals(openAPI.getTags().get(1).getDescription(), "desc definition"); assertEquals(openAPI.getTags().get(2).getExternalDocs().getDescription(), "docs desc"); } @Test(description = "Get servers") public void testGetServers() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ServersResource.class); Operation operation = openAPI.getPaths().get("/").getGet(); assertNotNull(operation); assertEquals(5, operation.getServers().size()); assertEquals(operation.getServers().get(0).getUrl(), "http://class1"); assertEquals(operation.getServers().get(1).getUrl(), "http://class2"); assertEquals(operation.getServers().get(2).getUrl(), "http://method1"); assertEquals(operation.getServers().get(3).getUrl(), "http://method2"); assertEquals(operation.getServers().get(4).getUrl(), "http://op1"); assertEquals(operation.getServers().get(0).getVariables().size(), 2); assertEquals(operation.getServers().get(0).getVariables().get("var1").getDescription(), "var 1"); assertEquals(operation.getServers().get(0).getVariables().get("var1").getEnum().size(), 2); assertEquals(openAPI.getServers().get(0).getDescription(), "definition server 1"); } @Test(description = "Responses") public void testGetResponses() { Reader reader = new Reader(new OpenAPI()); Method[] methods = ResponsesResource.class.getMethods(); Operation responseOperation = reader.parseMethod(Arrays.stream(methods).filter( (method -> method.getName().equals("getResponses"))).findFirst().get(), null, null); assertNotNull(responseOperation); ApiResponses responses = responseOperation.getResponses(); assertEquals(RESPONSES_NUMBER, responses.size()); ApiResponse apiResponse = responses.get(RESPONSE_CODE_200); assertNotNull(apiResponse); assertEquals(RESPONSE_DESCRIPTION, apiResponse.getDescription()); } @Test(description = "More Responses") public void testMoreResponses() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(EnhancedResponsesResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " object\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleResponseSchema\"\n" + " \"404\":\n" + " description: not found!\n" + " \"400\":\n" + " description: boo\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/GenericError\"\n" + " deprecated: true\n" + "components:\n" + " schemas:\n" + " GenericError:\n" + " type: object\n" + " SampleResponseSchema:\n" + " type: object\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Responses with composition") public void testGetResponsesWithComposition() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ResponsesResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " object\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleResponseSchema\"\n" + " default:\n" + " description: boo\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/GenericError\"\n" + " deprecated: true\n" + " /allOf:\n" + " get:\n" + " summary: Test inheritance / polymorphism\n" + " operationId: getAllOf\n" + " parameters:\n" + " - name: number\n" + " in: query\n" + " description: Test inheritance / polymorphism\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " example: 1\n" + " responses:\n" + " \"200\":\n" + " description: bean answer\n" + " content:\n" + " application/json:\n" + " schema:\n" + " allOf:\n" + " - $ref: \"#/components/schemas/MultipleSub1Bean\"\n" + " - $ref: \"#/components/schemas/MultipleSub2Bean\"\n" + " /anyOf:\n" + " get:\n" + " summary: Test inheritance / polymorphism\n" + " operationId: getAnyOf\n" + " parameters:\n" + " - name: number\n" + " in: query\n" + " description: Test inheritance / polymorphism\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " example: 1\n" + " responses:\n" + " \"200\":\n" + " description: bean answer\n" + " content:\n" + " application/json:\n" + " schema:\n" + " anyOf:\n" + " - $ref: \"#/components/schemas/MultipleSub1Bean\"\n" + " - $ref: \"#/components/schemas/MultipleSub2Bean\"\n" + " /oneOf:\n" + " get:\n" + " summary: Test inheritance / polymorphism\n" + " operationId: getOneOf\n" + " parameters:\n" + " - name: number\n" + " in: query\n" + " description: Test inheritance / polymorphism\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " example: 1\n" + " responses:\n" + " \"200\":\n" + " description: bean answer\n" + " content:\n" + " application/json:\n" + " schema:\n" + " oneOf:\n" + " - $ref: \"#/components/schemas/MultipleSub1Bean\"\n" + " - $ref: \"#/components/schemas/MultipleSub2Bean\"\n" + "components:\n" + " schemas:\n" + " SampleResponseSchema:\n" + " type: object\n" + " GenericError:\n" + " type: object\n" + " MultipleSub1Bean:\n" + " type: object\n" + " description: MultipleSub1Bean\n" + " allOf:\n" + " - $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " - type: object\n" + " properties:\n" + " c:\n" + " type: integer\n" + " format: int32\n" + " MultipleSub2Bean:\n" + " type: object\n" + " description: MultipleSub2Bean\n" + " allOf:\n" + " - $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " - type: object\n" + " properties:\n" + " d:\n" + " type: integer\n" + " format: int32\n" + " MultipleBaseBean:\n" + " type: object\n" + " properties:\n" + " beanType:\n" + " type: string\n" + " a:\n" + " type: integer\n" + " format: int32\n" + " b:\n" + " type: string\n" + " description: MultipleBaseBean"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "External Docs") public void testGetExternalDocs() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ExternalDocsReference.class); Operation externalDocsOperation = openAPI.getPaths().get("/").getGet(); ExternalDocumentation externalDocs = externalDocsOperation.getExternalDocs(); assertEquals(externalDocs.getDescription(), "External documentation description in method"); assertEquals(externalDocs.getUrl(), EXTERNAL_DOCS_URL); externalDocs = openAPI.getComponents().getSchemas().get("ExternalDocsSchema").getExternalDocs(); assertEquals("External documentation description in schema", externalDocs.getDescription()); assertEquals(externalDocs.getUrl(), EXTERNAL_DOCS_URL); } @Test(description = "OperationExtensions Tests") public void testOperationExtensions() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(OperationExtensionsResource.class); assertNotNull(openAPI); Map extensions = openAPI.getPaths().get("/").getGet().getExtensions(); assertEquals(extensions.size(), 2); assertNotNull(extensions.get("x-operation")); assertNotNull(extensions.get("x-operation-extensions")); } @Test(description = "ParameterExtensions Tests") public void testParameterExtensions() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ParameterExtensionsResource.class); assertNotNull(openAPI); Map extensions = openAPI.getPaths().get("/").getGet().getParameters().get(0).getExtensions(); assertNotNull(extensions); assertEquals(1, extensions.size()); assertNotNull(extensions.get("x-parameter")); } @Test(description = "RequestBody Tests") public void testRequestBodyExtensions() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(RequestBodyExtensionsResource.class); assertNotNull(openAPI); Map extensions = openAPI.getPaths().get("/user").getGet(). getRequestBody().getExtensions(); assertNotNull(extensions); assertEquals(extensions.size(), 2); assertNotNull(extensions.get("x-extension")); assertNotNull(extensions.get("x-extension2")); } @Test(description = "Extensions Tests") public void testExtensions() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ExtensionsResource.class); assertNotNull(openAPI); SerializationMatchers.assertEqualsToYaml(openAPI, ExtensionsResource.YAML); } @Test(description = "Security Requirement") public void testSecurityRequirement() { Reader reader = new Reader(new OpenAPI()); Method[] methods = SecurityResource.class.getDeclaredMethods(); Operation securityOperation = reader.parseMethod(Arrays.stream(methods).filter( (method -> method.getName().equals("getSecurity"))).findFirst().get(), null, null); assertNotNull(securityOperation); List securityRequirements = securityOperation.getSecurity(); assertNotNull(securityRequirements); assertEquals(SECURITY_REQUIREMENT_NUMBER, securityRequirements.size()); List scopes = securityRequirements.get(0).get(SECURITY_KEY); assertNotNull(scopes); assertEquals(SCOPE_NUMBER, scopes.size()); assertEquals(SCOPE_VALUE1, scopes.get(0)); assertEquals(SCOPE_VALUE2, scopes.get(1)); } @Test(description = "Callbacks") public void testGetCallbacks() { Reader reader = new Reader(new OpenAPI()); Method[] methods = SimpleCallbackResource.class.getMethods(); Operation callbackOperation = reader.parseMethod(methods[0], null, null); assertNotNull(callbackOperation); Map callbacks = callbackOperation.getCallbacks(); assertNotNull(callbacks); Callback callback = callbacks.get(CALLBACK_SUBSCRIPTION_ID); assertNotNull(callback); PathItem pathItem = callback.get(CALLBACK_URL); assertNotNull(pathItem); Operation postOperation = pathItem.getPost(); assertNotNull(postOperation); assertEquals(CALLBACK_POST_OPERATION_DESCRIPTION, postOperation.getDescription()); Operation getOperation = pathItem.getGet(); assertNotNull(getOperation); assertEquals(CALLBACK_GET_OPERATION_DESCRIPTION, getOperation.getDescription()); Operation putOperation = pathItem.getPut(); assertNotNull(putOperation); assertEquals(CALLBACK_POST_OPERATION_DESCRIPTION, putOperation.getDescription()); } @Test(description = "Get the Param of an operation") public void testSubscriptionIdParam() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(BasicFieldsResource.class); assertNotNull(openAPI); Paths openAPIPaths = openAPI.getPaths(); assertNotNull(openAPIPaths); PathItem pathItem = openAPIPaths.get(PATH_1_REF); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); List parameters = operation.getParameters(); assertNotNull(parameters); assertEquals(PARAMETER_NUMBER, parameters.size()); Parameter parameter = parameters.get(0); assertNotNull(parameter); assertEquals(PARAMETER_IN, parameter.getIn()); assertEquals(PARAMETER_NAME, parameter.getName()); assertEquals(PARAMETER_DESCRIPTION, parameter.getDescription()); assertEquals(Boolean.TRUE, parameter.getRequired()); assertEquals(Boolean.TRUE, parameter.getAllowEmptyValue()); assertEquals(Boolean.TRUE, parameter.getAllowReserved()); Schema schema = parameter.getSchema(); assertNotNull(schema); assertEquals(SCHEMA_TYPE, schema.getType()); assertEquals(SCHEMA_FORMAT, schema.getFormat()); assertEquals(SCHEMA_DESCRIPTION, schema.getDescription()); assertEquals(Boolean.TRUE, schema.getReadOnly()); } private Boolean isValidRestPath(Method method) { for (Class item : Arrays.asList(GET.class, PUT.class, POST.class, DELETE.class, OPTIONS.class, HEAD.class)) { if (method.getAnnotation(item) != null) { return true; } } return false; } @Test public void testClassWithGenericType() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ClassWithGenericType.class); assertNotNull(openAPI); assertNotNull(openAPI.getComponents().getSchemas().get("IssueTemplateRet")); assertNotNull(openAPI.getComponents().getSchemas().get("B")); assertNotNull(openAPI.getComponents().getSchemas().get("B").getProperties().get("test")); assertEquals(((Schema) openAPI.getComponents().getSchemas().get("B").getProperties().get("test")).get$ref(), "#/components/schemas/IssueTemplateRet"); //Yaml.prettyPrint(openAPI); } public static class A { public B b; } public static class IssueTemplate { public T getTemplateTest() { return null; } public String getTemplateTestString() { return null; } } public static class B { public IssueTemplate getTest() { return null; } } public static class Ret { public String c; } static class ClassWithGenericType { @Path("/test") @Produces("application/json") @Consumes("application/json") @GET @io.swagger.v3.oas.annotations.Operation(tags = "/receiver/rest") //public void test1(@QueryParam("aa") String a) { public void test1(A a) { } } @Test public void testClassWithCompletableFuture() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ClassWithCompletableFuture.class); assertNotNull(openAPI); assertEquals( openAPI.getPaths() .get("/myApi") .getGet() .getResponses() .get("default") .getContent() .get("application/json") .getSchema() .get$ref(), "#/components/schemas/Ret" ); } static class ClassWithCompletableFuture { @Path("/myApi") @Produces("application/json") @Consumes("application/json") @GET public CompletableFuture myApi(A a) { return CompletableFuture.completedFuture(new Ret()); } } @Test(description = "test resource with array in response content") public void test2497() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ResponseContentWithArrayResource.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 1); PathItem pathItem = paths.get("/user"); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); ArraySchema schema = (ArraySchema) operation.getResponses().get("200").getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getItems().get$ref(), "#/components/schemas/User"); assertEquals(openAPI.getComponents().getSchemas().get("User").getRequired().get(0), "issue3438"); } @Test(description = "array required property resolved from ArraySchema.arraySchema.requiredMode") public void test4341() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket4341Resource.class); Schema userSchema = openAPI.getComponents().getSchemas().get("User"); List required = userSchema.getRequired(); assertTrue(required.contains("requiredArray")); assertFalse(required.contains("notRequiredArray")); assertFalse(required.contains("notRequiredArrayWithNotNull")); assertTrue(required.contains("autoRequiredWithNotNull")); assertFalse(required.contains("autoNotRequired")); assertTrue( required.contains("requiredArrayArraySchemaOnly"), "arraySchema.requiredMode=REQUIRED should make the array property required " + "even when items schema is not explicitly provided" ); assertFalse( required.contains("requiredItemsOnlyArray"), "schema(requiredMode=REQUIRED) on items must not make the array property required; " + "requiredness is controlled by arraySchema.requiredMode" ); } @Test(description = "test resource with subresources") public void testResourceWithSubresources() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ResourceWithSubResource.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 3); PathItem pathItem = paths.get("/employees/{id}"); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); ArraySchema arraySchema = (ArraySchema) operation.getResponses().get("200").getContent().values().iterator().next().getSchema(); assertNotNull(arraySchema); assertEquals(arraySchema.getItems().get$ref(), "#/components/schemas/Pet"); pathItem = paths.get("/employees/{id}/{id}"); assertNotNull(pathItem); operation = pathItem.getGet(); assertNotNull(operation); Schema schema = operation.getResponses().get("200").getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.get$ref(), "#/components/schemas/Pet"); pathItem = paths.get("/employees/noPath"); assertNotNull(pathItem); operation = pathItem.getGet(); assertNotNull(operation); schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); } @Test(description = "test another resource with subresources") public void testAnotherResourceWithSubresources() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(TestResource.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 3); PathItem pathItem = paths.get("/test/status"); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("application/json")); Schema schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); pathItem = paths.get("/test/more/otherStatus"); assertNotNull(pathItem); operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("application/json")); assertFalse(operation.getResponses().getDefault().getContent().keySet().contains("application/xml")); schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); pathItem = paths.get("/test/evenmore/otherStatus"); assertNotNull(pathItem); operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("application/json")); assertFalse(operation.getResponses().getDefault().getContent().keySet().contains("application/xml")); schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); assertEquals(operation.getRequestBody().getContent().get("application/json").getSchema().get$ref(), "#/components/schemas/Pet"); } @Test(description = "test user annotation") public void testUserAnnotation() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(UserAnnotationResource.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 1); PathItem pathItem = paths.get("/test/status"); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getTags().contains("test")); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("application/json")); Schema schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); } @Test(description = "scan resource with class-based sub-resources") public void testResourceWithClassBasedSubresources() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(SubResourceHead.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 3); PathItem pathItem = paths.get("/head/tail/hello"); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("*/*")); Schema schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); pathItem = paths.get("/head/tail/{string}"); assertNotNull(pathItem); operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("*/*")); schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); pathItem = paths.get("/head/noPath"); assertNotNull(pathItem); operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("*/*")); schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); } @Test(description = "test ticket #2607 resource with subresources") public void test2607() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Test2607.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 2); PathItem pathItem = paths.get("/swaggertest/name"); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("text/plain")); Schema schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); pathItem = paths.get("/swaggertest/subresource/version"); assertNotNull(pathItem); operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("text/plain")); schema = operation.getResponses().getDefault().getContent().values().iterator().next().getSchema(); assertNotNull(schema); assertEquals(schema.getType(), "string"); } @Test(description = "test ticket #2646 method annotated with @Produce") public void test2646() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(BookStoreTicket2646.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 2); PathItem pathItem = paths.get("/bookstore"); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("application/json")); pathItem = paths.get("/bookstore/{id}"); assertNotNull(pathItem); operation = pathItem.getDelete(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("*/*")); } @Test(description = "test ticket #2644 annotated interface") public void test2644() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket2644ConcreteImplementation.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 1); PathItem pathItem = paths.get("/resources"); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().getDefault().getContent().keySet().contains("*/*")); } @Test(description = "Scan subresource per #2632") public void testSubResourceHasTheRightApiPath() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ClassPathParentResource.class); assertNotNull(openAPI); assertNotNull(openAPI.getPaths().get("/v1/parent")); assertNotNull(openAPI.getPaths().get("/v1/parent/{id}")); assertEquals(openAPI.getPaths().size(), 2); OpenAPI subResourceApi = new Reader(new OpenAPI()).read(ClassPathSubResource.class); assertNotNull(subResourceApi); assertNotNull(subResourceApi.getPaths().get("/subresource")); assertNotNull(subResourceApi.getPaths().get("/subresource/{id}")); assertEquals(subResourceApi.getPaths().size(), 2); } @Test(description = "Resolve Model with XML Properties starting with is prefix per #2635") public void testModelResolverXMLPropertiesName() { final MyClass myClass = new MyClass(); myClass.populate("isotonicDrink value", "softDrink value", "isoDrink value", "isotonicDrinkOnlyXmlElement value"); Map schemas = resolveJaxb(MyClass.class); assertNull(schemas.get("MyClass").getProperties().get("isotonicDrink")); assertNotNull(schemas.get("MyClass").getProperties().get("beerDrink")); assertNotNull(schemas.get("MyClass").getProperties().get("saltDrink")); // No JsonProperty or ApiModelProperty, keep original name assertNull(schemas.get("MyClass").getProperties().get("beerDrinkXmlElement")); assertNotNull(schemas.get("MyClass").getProperties().get("isotonicDrinkOnlyXmlElement")); } @Test(description = "Maintain Property names per #2635") public void testMaintainPropertyNames() { final MyOtherClass myOtherClass = new MyOtherClass(); myOtherClass.populate("myPropertyName value"); Map schemas = resolveJaxb(MyOtherClass.class); assertNotNull(schemas.get("MyOtherClass").getProperties().get("MyPrOperTyName")); } private Map resolveJaxb(Type type) { List converters = new CopyOnWriteArrayList (); ObjectMapper mapper = JaxbObjectMapperFactory.getMapper(); converters.add(new ModelResolver(mapper)); ModelConverterContextImpl context = new ModelConverterContextImpl( converters); Schema resolve = context.resolve(new AnnotatedType().type(type)); Map schemas = new HashMap(); for (Map.Entry entry : context.getDefinedModels() .entrySet()) { if (entry.getValue().equals(resolve)) { schemas.put(entry.getKey(), entry.getValue()); } } return schemas; } @Test(description = "Responses with array schema") public void testTicket2763() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket2763Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /array:\n" + " get:\n" + " operationId: getArrayResponses\n" + " responses:\n" + " default:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: https://openebench.bsc.es/monitor/tool/tool.json\n" + " /schema:\n" + " get:\n" + " operationId: getSchemaResponses\n" + " responses:\n" + " default:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: https://openebench.bsc.es/monitor/tool/tool.json"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Responses with array schema") public void testTicket2340() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket2340Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/test:\n" + " post:\n" + " operationId: getAnimal\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Animal\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: string\n" + "components:\n" + " schemas:\n" + " Animal:\n" + " required:\n" + " - type\n" + " type: object\n" + " properties:\n" + " type:\n" + " type: string\n" + " discriminator:\n" + " propertyName: type\n" + " Cat:\n" + " type: object\n" + " allOf:\n" + " - $ref: \"#/components/schemas/Animal\"\n" + " - type: object\n" + " properties:\n" + " lives:\n" + " type: integer\n" + " format: int32\n" + " Dog:\n" + " type: object\n" + " allOf:\n" + " - $ref: \"#/components/schemas/Animal\"\n" + " - type: object\n" + " properties:\n" + " barkVolume:\n" + " type: number\n" + " format: double\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "array schema example") public void testTicket2806() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket2806Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test:\n" + " get:\n" + " operationId: getTest\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Test\"\n" + "components:\n" + " schemas:\n" + " Test:\n" + " type: object\n" + " properties:\n" + " stringArray:\n" + " maxItems: 4\n" + " minItems: 2\n" + " uniqueItems: true\n" + " type: array\n" + " description: Array desc\n" + " example:\n" + " - aaa\n" + " - bbb\n" + " items:\n" + " type: string\n" + " description: Hello, World!\n" + " example: Lorem ipsum dolor set\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "NotNull parameters") public void testTicket2794() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket2794Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /notnullparameter:\n" + " get:\n" + " operationId: getBooks\n" + " parameters:\n" + " - name: page\n" + " in: query\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n" + " /notnullparameter/newnotnull:\n" + " post:\n" + " operationId: insertnotnull\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Book\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /notnullparameter/new_reqBody_required:\n" + " post:\n" + " operationId: insert\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Book\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Book:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } /* TODO: in a scenario like the one in ticket 2793, currently no NPE is thrown but map is still not supported. When solved, update expected yaml in test case accordingly */ @Test(description = "no NPE resolving map") public void testTicket2793() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket2793Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /distances:\n" + " get:\n" + " operationId: getDistances\n" + " responses:\n" + " \"200\":\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/DistancesResponse\"\n" + "components:\n" + " schemas:\n" + " DistancesResponse:\n" + " type: object\n" + " properties:\n" + " empty:\n" + " type: boolean\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "test ticket #2818 @Parameter annotation") public void test2818() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket2818Resource.class); Paths paths = openAPI.getPaths(); assertEquals(paths.size(), 1); PathItem pathItem = paths.get("/bookstore/{id}"); assertNotNull(pathItem); Operation operation = pathItem.getGet(); assertNotNull(operation); assertEquals(operation.getParameters().get(0).getSchema().getType(), "integer"); assertEquals(operation.getParameters().get(0).getSchema().getFormat(), "int32"); } @Test(description = "Responses with ref") public void testResponseWithRef() { Components components = new Components(); components.addResponses("invalidJWT", new ApiResponse().description("when JWT token invalid/expired")); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(RefResponsesResource.class); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " object\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleResponseSchema\"\n" + " default:\n" + " description: boo\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/GenericError\"\n" + " \"401\":\n" + " $ref: \"#/components/responses/invalidJWT\"\n" + " deprecated: true\n" + "components:\n" + " schemas:\n" + " GenericError:\n" + " type: object\n" + " SampleResponseSchema:\n" + " type: object\n" + " responses:\n" + " invalidJWT:\n" + " description: when JWT token invalid/expired"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Responses with filter") public void testResponseWithFilter() { Components components = new Components(); components.addResponses("invalidJWT", new ApiResponse().description("when JWT token invalid/expired")); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(SimpleResponsesResource.class); OpenAPISpecFilter filterImpl = new RefResponseFilter(); SpecFilter f = new SpecFilter(); openAPI = f.filter(openAPI, filterImpl, null, null, null); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " object\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleResponseSchema\"\n" + " default:\n" + " description: boo\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/GenericError\"\n" + " \"401\":\n" + " $ref: \"#/components/responses/invalidJWT\"\n" + " deprecated: true\n" + "components:\n" + " schemas:\n" + " GenericError:\n" + " type: object\n" + " SampleResponseSchema:\n" + " type: object\n" + " responses:\n" + " invalidJWT:\n" + " description: when JWT token invalid/expired"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } class RefResponseFilter extends AbstractSpecFilter { @Override public Optional filterOperation(Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if ("getWithPayloadResponse".equals(operation.getOperationId())) { final ApiResponses apiResponses = (operation.getResponses() == null) ? new ApiResponses() : operation.getResponses(); apiResponses.addApiResponse("401", new ApiResponse().$ref("#/components/responses/invalidJWT")); operation.setResponses(apiResponses); return Optional.of(operation); } return super.filterOperation(operation, api, params, cookies, headers); } } @Test(description = "array schema required property") public void testTicket2848() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket2848Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " operationId: getter\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Town\"\n" + "components:\n" + " schemas:\n" + " Town:\n" + " required:\n" + " - streets\n" + " type: object\n" + " properties:\n" + " streets:\n" + " minItems: 1\n" + " uniqueItems: true\n" + " type: array\n" + " items:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "RequestBody with ref") public void testRequestBodyWithRef() { Components components = new Components(); components.addRequestBodies("User", new RequestBody().description("Test RequestBody")); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(RefRequestBodyResource.class); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with a payload complex input object\n" + " operationId: sendPayload\n" + " requestBody:\n" + " $ref: \"#/components/requestBodies/User\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " deprecated: true\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " username:\n" + " type: string\n" + " firstName:\n" + " type: string\n" + " lastName:\n" + " type: string\n" + " email:\n" + " type: string\n" + " password:\n" + " type: string\n" + " phone:\n" + " type: string\n" + " userStatus:\n" + " type: integer\n" + " description: User Status\n" + " format: int32\n" + " xml:\n" + " name: User\n" + " requestBodies:\n" + " User:\n" + " description: Test RequestBody\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "RequestBody with filter") public void testRequestBodyWithFilter() { Components components = new Components(); components.addRequestBodies("User", new RequestBody()); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(SimpleRequestBodyResource.class); OpenAPISpecFilter filterImpl = new RefRequestBodyFilter(); SpecFilter f = new SpecFilter(); openAPI = f.filter(openAPI, filterImpl, null, null, null); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with a payload complex input object\n" + " operationId: sendPayload\n" + " requestBody:\n" + " $ref: \"#/components/requestBodies/User\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " deprecated: true\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " username:\n" + " type: string\n" + " firstName:\n" + " type: string\n" + " lastName:\n" + " type: string\n" + " email:\n" + " type: string\n" + " password:\n" + " type: string\n" + " phone:\n" + " type: string\n" + " userStatus:\n" + " type: integer\n" + " description: User Status\n" + " format: int32\n" + " xml:\n" + " name: User\n" + " requestBodies:\n" + " User: {}\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } class RefRequestBodyFilter extends AbstractSpecFilter { @Override public Optional filterOperation(Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if ("sendPayload".equals(operation.getOperationId())) { final RequestBody requestBody = new RequestBody(); requestBody.set$ref("#/components/requestBodies/User"); operation.setRequestBody(requestBody); return Optional.of(operation); } return super.filterOperation(operation, api, params, cookies, headers); } } @Test(description = "Parameter with ref") public void testParameterWithRef() { Components components = new Components(); components.addParameters("id", new Parameter() .description("Id Description") .schema(new IntegerSchema()) .in(ParameterIn.QUERY.toString()) .example(1) .required(true)); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(RefParameterResource.class); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with a payload complex input object\n" + " operationId: sendPayload\n" + " parameters:\n" + " - $ref: \"#/components/parameters/id\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " deprecated: true\n" + "components:\n" + " parameters: \n" + " id:\n" + " in: query\n" + " description: Id Description\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " example: 1\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Responses with filter") public void testParameterWithFilter() { Components components = new Components(); components.addParameters("id", new Parameter() .description("Id Description") .schema(new IntegerSchema()) .in(ParameterIn.QUERY.toString()) .example(1) .required(true)); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(SimpleParameterResource.class); OpenAPISpecFilter filterImpl = new RefParameterFilter(); SpecFilter f = new SpecFilter(); openAPI = f.filter(openAPI, filterImpl, null, null, null); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with a payload complex input object\n" + " operationId: sendPayload\n" + " parameters:\n" + " - $ref: \"#/components/parameters/id\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " deprecated: true\n" + "components:\n" + " parameters: \n" + " id:\n" + " in: query\n" + " description: Id Description\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " example: 1\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } class RefParameterFilter extends AbstractSpecFilter { @Override public Optional filterOperation(Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if ("sendPayload".equals(operation.getOperationId())) { final Parameter parameter = new Parameter(); parameter.set$ref("#/components/parameters/id"); operation.getParameters().clear(); operation.addParametersItem(parameter); return Optional.of(operation); } return super.filterOperation(operation, api, params, cookies, headers); } } @Test(description = "Example with ref") public void testExampleWithRef() { Components components = new Components(); components.addExamples("Id", new Example().description("Id Example").summary("Id Example").value("1")); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(RefExamplesResource.class); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /example:\n" + " post:\n" + " description: subscribes a client to updates relevant to the requestor's account\n" + " operationId: subscribe\n" + " parameters:\n" + " - name: subscriptionId\n" + " in: path\n" + " required: true\n" + " style: simple\n" + " schema:\n" + " type: string\n" + " description: Schema\n" + " example: Subscription example\n" + " examples:\n" + " subscriptionId_1:\n" + " summary: Subscription number 12345\n" + " description: subscriptionId_1\n" + " value: 12345\n" + " externalValue: Subscription external value 1\n" + " $ref: \"#/components/examples/Id\"\n" + " example: example\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + "components:\n" + " schemas:\n" + " SubscriptionResponse:\n" + " type: object\n" + " properties:\n" + " subscriptionId:\n" + " type: string\n" + " examples:\n" + " Id:\n" + " summary: Id Example\n" + " description: Id Example\n" + " value: \"1\"\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Example with Ref Filter") public void testExampleWithFilter() { Components components = new Components(); components.addExamples("Id", new Example().description("Id Example").summary("Id Example").value("1")); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(SimpleExamplesResource.class); OpenAPISpecFilter filterImpl = new RefExampleFilter(); SpecFilter f = new SpecFilter(); openAPI = f.filter(openAPI, filterImpl, null, null, null); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /example:\n" + " post:\n" + " description: subscribes a client to updates relevant to the requestor's account\n" + " operationId: subscribe\n" + " parameters:\n" + " - example:\n" + " $ref: \"#/components/examples/Id\"\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + "components:\n" + " schemas:\n" + " SubscriptionResponse:\n" + " type: object\n" + " properties:\n" + " subscriptionId:\n" + " type: string\n" + " examples:\n" + " Id:\n" + " summary: Id Example\n" + " description: Id Example\n" + " value: \"1\"\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } class RefExampleFilter extends AbstractSpecFilter { @Override public Optional filterOperation(Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { if ("subscribe".equals(operation.getOperationId())) { final Parameter parameter = new Parameter(); parameter.setExample(new Example().$ref("#/components/examples/Id")); operation.getParameters().clear(); operation.addParametersItem(parameter); return Optional.of(operation); } return super.filterOperation(operation, api, params, cookies, headers); } } @Test(description = "Header with Ref") public void testHeaderWithRef() { Components components = new Components(); components.addHeaders("Header", new Header().description("Header Description")); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(RefHeaderResource.class); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /path:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " headers:\n" + " Rate-Limit-Limit:\n" + " description: The number of allowed requests in the current period\n" + " $ref: \"#/components/headers/Header\"\n" + " style: simple\n" + " schema:\n" + " type: integer\n" + " deprecated: true\n" + "components:\n" + " headers:\n" + " Header:\n" + " description: Header Description\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "SecurityScheme with REf") public void testSecuritySchemeWithRef() { Components components = new Components(); components.addSecuritySchemes("Security", new SecurityScheme().description("Security Example"). name("Security").type(SecurityScheme.Type.OAUTH2).$ref("myOauth2Security").in(SecurityScheme.In.HEADER)); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(RefSecurityResource.class); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /:\n" + " get:\n" + " description: description\n" + " operationId: Operation Id\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " security:\n" + " - security_key:\n" + " - write:pets\n" + " - read:pets\n" + "components:\n" + " securitySchemes:\n" + " Security:\n" + " type: oauth2\n" + " description: Security Example\n" + " myOauth2Security:\n" + " type: oauth2\n" + " description: myOauthSecurity Description\n" + " $ref: \"#/components/securitySchemes/Security\"\n" + " in: header\n" + " flows:\n" + " implicit:\n" + " authorizationUrl: http://x.com\n" + " scopes:\n" + " write:pets: modify pets in your account\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Link with Ref") public void testLinkWithRef() { Components components = new Components(); components.addLinks("Link", new Link().description("Link Description").operationId("id")); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(RefLinksResource.class); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /links:\n" + " get:\n" + " operationId: getUserWithAddress\n" + " parameters:\n" + " - name: userId\n" + " in: query\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " links:\n" + " address:\n" + " operationId: getAddress\n" + " parameters:\n" + " userId: $request.query.userId\n" + " $ref: \"#/components/links/Link\"\n" + "components:\n" + " links:\n" + " Link:\n" + " operationId: id\n" + " description: Link Description\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Callback with Ref") public void testCallbackWithRef() { Components components = new Components(); components.addCallbacks("Callback", new Callback().addPathItem("/post", new PathItem().description("Post Path Item"))); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(RefCallbackResource.class); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /simplecallback:\n" + " get:\n" + " summary: Simple get operation\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " callbacks:\n" + " testCallback1:\n" + " $ref: \"#/components/callbacks/Callback\"\n" + "components:\n" + " callbacks:\n" + " Callback:\n" + " /post:\n" + " description: Post Path Item\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test public void testTicket3015() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket3015Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/test:\n" + " get:\n" + " operationId: schemaImpl\n" + " responses:\n" + " \"200\":\n" + " description: OK\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string\n" + " format: uri\n" + " \"400\":\n" + " description: Bad Request\n" + " \"500\":\n" + " description: Internal Server Error\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); PrimitiveType.customExcludedClasses().add(URI.class.getName()); openAPI = reader.read(Ticket3015Resource.class); yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/test:\n" + " get:\n" + " operationId: schemaImpl_1\n" + " responses:\n" + " \"200\":\n" + " description: OK\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " scheme:\n" + " type: string\n" + " fragment:\n" + " type: string\n" + " authority:\n" + " type: string\n" + " userInfo:\n" + " type: string\n" + " host:\n" + " type: string\n" + " port:\n" + " type: integer\n" + " format: int32\n" + " path:\n" + " type: string\n" + " query:\n" + " type: string\n" + " schemeSpecificPart:\n" + " type: string\n" + " rawSchemeSpecificPart:\n" + " type: string\n" + " rawAuthority:\n" + " type: string\n" + " rawUserInfo:\n" + " type: string\n" + " rawPath:\n" + " type: string\n" + " rawQuery:\n" + " type: string\n" + " rawFragment:\n" + " type: string\n" + " absolute:\n" + " type: boolean\n" + " opaque:\n" + " type: boolean\n" + " \"400\":\n" + " description: Bad Request\n" + " \"500\":\n" + " description: Internal Server Error\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); PrimitiveType.customExcludedClasses().remove(URI.class.getName()); } @Test(description = "Parameter with ref") public void testTicket3029() { Components components = new Components(); components.addParameters("id", new Parameter() .description("Id Description") .schema(new IntegerSchema()) .in(ParameterIn.QUERY.toString()) .example(1) .required(true)); OpenAPI oas = new OpenAPI() .info(new Info().description("info")) .components(components); Reader reader = new Reader(oas); OpenAPI openAPI = reader.read(RefParameter3029Resource.class); String yaml = "openapi: 3.0.1\n" + "info:\n" + " description: info\n" + "paths:\n" + " /2:\n" + " get:\n" + " summary: Simple get operation\n" + " operationId: sendPayload2\n" + " parameters:\n" + " - $ref: \"#/components/parameters/id\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /1:\n" + " get:\n" + " summary: Simple get operation\n" + " operationId: sendPayload1\n" + " parameters:\n" + " - $ref: \"#/components/parameters/id\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " parameters:\n" + " id:\n" + " in: query\n" + " description: Id Description\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " example: 1\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "response generic subclass") public void testTicket3082() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ProcessTokenRestService.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /token:\n" + " post:\n" + " operationId: create\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/ProcessTokenDTO\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/ProcessTokenDTO\"\n" + "components:\n" + " schemas:\n" + " ProcessTokenDTO:\n" + " type: object\n" + " properties:\n" + " guid:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Filter class return type") public void testTicket3074() { Reader reader = new Reader(new OpenAPI()); OpenAPI oasResult = reader.read(RefParameter3074Resource.class); SerializationMatchers.assertEqualsToYaml(oasResult, RefParameter3074Resource.EXPECTED_YAML_WITH_WRAPPER); ModelConverters.getInstance().addClassToSkip("io.swagger.v3.jaxrs2.resources.RefParameter3074Resource$Wrapper"); reader = new Reader(new OpenAPI()); oasResult = reader.read(RefParameter3074Resource.class); SerializationMatchers.assertEqualsToYaml(oasResult, RefParameter3074Resource.EXPECTED_YAML_WITHOUT_WRAPPER); } @Test(description = "Single Example") public void testSingleExample() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(SingleExampleResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test1:\n" + " post:\n" + " operationId: test1\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " example:\n" + " foo: foo\n" + " bar: bar\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test2:\n" + " post:\n" + " operationId: test2\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " example:\n" + " foo: foo\n" + " bar: bar\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " username:\n" + " type: string\n" + " firstName:\n" + " type: string\n" + " lastName:\n" + " type: string\n" + " email:\n" + " type: string\n" + " password:\n" + " type: string\n" + " phone:\n" + " type: string\n" + " userStatus:\n" + " type: integer\n" + " description: User Status\n" + " format: int32\n" + " xml:\n" + " name: User\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test public void testTicket3092() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(UploadResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /upload:\n" + " post:\n" + " operationId: uploadWithBean\n" + " requestBody:\n" + " content:\n" + " multipart/form-data:\n" + " schema:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " picture:\n" + " $ref: \"#/components/schemas/picture\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n" + " /upload/requestbody:\n" + " post:\n" + " operationId: uploadWithBeanAndRequestBody\n" + " requestBody:\n" + " content:\n" + " multipart/form-data:\n" + " schema:\n" + " $ref: \"#/components/schemas/UploadRequest\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n" + "components:\n" + " schemas:\n" + " picture:\n" + " type: object\n" + " format: binary\n" + " UploadRequest:\n" + " title: Schema for Upload\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " picture:\n" + " type: string\n" + " format: binary"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Parameter examples ordering") public void testTicket3587() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket3587Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/test:\n" + " get:\n" + " operationId: parameterExamplesOrderingTest\n" + " parameters:\n" + " - in: query\n" + " schema:\n" + " type: string\n" + " examples:\n" + " Example One:\n" + " description: Example One\n" + " Example Two:\n" + " description: Example Two\n" + " Example Three:\n" + " description: Example Three\n" + " - in: query\n" + " schema:\n" + " type: string\n" + " examples:\n" + " Example Three:\n" + " description: Example Three\n" + " Example Two:\n" + " description: Example Two\n" + " Example One:\n" + " description: Example One\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}"; SerializationMatchers.assertEqualsToYamlExact(openAPI, yaml); } @Test(description = "Optional handling") public void testTicket3624() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Service.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /example/model:\n" + " get:\n" + " tags:\n" + " - ExampleService\n" + " summary: ' Retrieve models for display to the user'\n" + " operationId: getModels\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Response\"\n" + " /example/model/by/ids:\n" + " get:\n" + " tags:\n" + " - ExampleService\n" + " summary: ' Retrieve models by their ids'\n" + " operationId: getModelsById\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/ByIdResponse\"\n" + " /example/containerized/model:\n" + " get:\n" + " tags:\n" + " - ExampleService\n" + " summary: ' Retrieve review insights for a specific product'\n" + " operationId: getContainerizedModels\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/ContainerizedResponse\"\n" + "components:\n" + " schemas:\n" + " Model:\n" + " type: object\n" + " properties:\n" + " text:\n" + " type: string\n" + " title:\n" + " type: string\n" + " active:\n" + " type: boolean\n" + " schemaParent:\n" + " $ref: \"#/components/schemas/Model\"\n" + " optionalString:\n" + " type: string\n" + " parent:\n" + " $ref: \"#/components/schemas/Model\"\n" + " id:\n" + " type: integer\n" + " format: int32\n" + " Response:\n" + " type: object\n" + " properties:\n" + " count:\n" + " type: integer\n" + " format: int32\n" + " models:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Model\"\n" + " ByIdResponse:\n" + " type: object\n" + " properties:\n" + " modelsById:\n" + " type: object\n" + " additionalProperties:\n" + " $ref: \"#/components/schemas/Model\"\n" + " ContainerizedResponse:\n" + " type: object\n" + " properties:\n" + " totalCount:\n" + " type: integer\n" + " format: int32\n" + " containerizedModels:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/ModelContainer\"\n" + " ModelContainer:\n" + " type: object\n" + " properties:\n" + " text:\n" + " type: string\n" + " model:\n" + " $ref: \"#/components/schemas/Model\"\n" + " id:\n" + " type: integer\n" + " format: int32"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test public void testRequestBodyEncoding() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(UrlEncodedResourceWithEncodings.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /things/search:\n" + " post:\n" + " operationId: searchForThings\n" + " requestBody:\n" + " content:\n" + " application/x-www-form-urlencoded:\n" + " schema:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: array\n" + " description: id param\n" + " items:\n" + " type: string\n" + " name:\n" + " type: array\n" + " items:\n" + " type: string\n" + " encoding:\n" + " id:\n" + " style: form\n" + " explode: true\n" + " name:\n" + " style: form\n" + " explode: false\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n" + " /things/sriracha:\n" + " post:\n" + " operationId: srirachaThing\n" + " requestBody:\n" + " content:\n" + " application/x-www-form-urlencoded:\n" + " schema:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: array\n" + " description: id param\n" + " items:\n" + " type: string\n" + " name:\n" + " type: array\n" + " items:\n" + " type: string\n" + " encoding:\n" + " id:\n" + " style: form\n" + " explode: true\n" + " name:\n" + " style: form\n" + " explode: false\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "overridden generic resource methods") public void testTicket3694() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket3694ResourceExtendedType.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /foo:\n" + " post:\n" + " tags:\n" + " - Foo\n" + " summary: Foo List in Interface\n" + " operationId: foo\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /bar:\n" + " post:\n" + " operationId: bar\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string\n" + " /another:\n" + " post:\n" + " operationId: another\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); reader = new Reader(new OpenAPI()); openAPI = reader.read(Ticket3694Resource.class); yaml = "openapi: 3.0.1\n" + "paths:\n" + " /foo:\n" + " post:\n" + " tags:\n" + " - Foo\n" + " summary: Foo List in Interface\n" + " operationId: foo\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /bar:\n" + " post:\n" + " operationId: bar\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string\n" + " /another:\n" + " post:\n" + " operationId: another\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); reader = new Reader(new OpenAPI()); openAPI = reader.read(Ticket3694ResourceSimple.class); yaml = "openapi: 3.0.1\n" + "paths:\n" + " /bar:\n" + " post:\n" + " operationId: bar\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); reader = new Reader(new OpenAPI()); openAPI = reader.read(Ticket3694ResourceSimpleSameReturn.class); yaml = "openapi: 3.0.1\n" + "paths:\n" + " /bar:\n" + " post:\n" + " operationId: bar\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "non consistent overridden generic resource methods") public void testTicket2144() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ItemResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /item/{id}:\n" + " get:\n" + " operationId: getById\n" + " parameters:\n" + " - name: id\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/ItemWithChildren\"\n" + " /item/nogeneric/{id}:\n" + " get:\n" + " operationId: getByIdNoGeneric\n" + " parameters:\n" + " - name: id\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/ItemWithChildren\"\n" + " /item/nogenericsamereturn/{id}:\n" + " get:\n" + " operationId: getByIdNoGenericSameReturn\n" + " parameters:\n" + " - name: id\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/BaseDTO\"\n" + " /item/genericparam:\n" + " post:\n" + " operationId: genericParam\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/ItemWithChildren\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/BaseDTO\"\n" + "components:\n" + " schemas:\n" + " ItemWithChildren:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " names:\n" + " type: string\n" + " BaseDTO:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "overridden generic resource interface default methods") public void testTicket3149() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(MainResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test:\n" + " post:\n" + " tags:\n" + " - Test inheritance on default implementation in interfaces\n" + " operationId: firstEndpoint\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleDTO\"\n" + " responses:\n" + " \"201\":\n" + " description: Created\n" + " \"400\":\n" + " description: Bad Request\n" + " \"403\":\n" + " description: Forbidden\n" + " \"404\":\n" + " description: Not Found\n" + " /test/{id}:\n" + " get:\n" + " tags:\n" + " - Test inheritance on default implementation in interfaces\n" + " operationId: secondEnpoint\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleOtherDTO\"\n" + " responses:\n" + " \"200\":\n" + " description: OK\n" + " \"400\":\n" + " description: Bad Request\n" + " \"403\":\n" + " description: Forbidden\n" + " \"404\":\n" + " description: Not Found\n" + " /test/original/{id}:\n" + " get:\n" + " tags:\n" + " - Test inheritance on default implementation in interfaces\n" + " operationId: originalEndpoint\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleOtherDTO\"\n" + " responses:\n" + " \"200\":\n" + " description: OK\n" + " \"400\":\n" + " description: Bad Request\n" + " \"403\":\n" + " description: Forbidden\n" + " \"404\":\n" + " description: Not Found\n" + "components:\n" + " schemas:\n" + " SampleDTO:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " SampleOtherDTO:\n" + " type: object\n" + " properties:\n" + " label:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "overridden generic resource methods operationId") public void testTicket3426() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket3426Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /inheritExample/{input}:\n" + " get:\n" + " operationId: get\n" + " parameters:\n" + " - name: input\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Constraints annotations in models") public void testTicket3731() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket3731Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/cart:\n" + " get:\n" + " summary: Get cart items\n" + " description: Paging follows RFC 5005.\n" + " operationId: getCart\n" + " parameters:\n" + " - name: pageSize\n" + " in: query\n" + " description: \"Number of items per page. Range[1, 200]\"\n" + " schema:\n" + " maximum: 200\n" + " minimum: 1\n" + " type: integer\n" + " format: int32\n" + " default: 50\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); reader = new Reader(new OpenAPI()); openAPI = reader.read(Ticket3731BisResource.class); SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Test SchemaProperties and additionalProperties annotations") public void testSchemaProperties() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(SchemaPropertiesResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " object\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " maximum: 1\n" + " type: integer\n" + " default:\n" + " description: boo\n" + " content:\n" + " application/json:\n" + " schema:\n" + " maxProperties: 3\n" + " type: object\n" + " properties:\n" + " foo:\n" + " maximum: 1\n" + " type: integer\n" + " description: various properties\n" + " \"400\":\n" + " description: additionalProperties schema\n" + " content:\n" + " application/json:\n" + " schema:\n" + " maxProperties: 2\n" + " type: object\n" + " additionalProperties:\n" + " type: string\n" + " \"401\":\n" + " description: additionalProperties boolean\n" + " content:\n" + " application/json:\n" + " schema:\n" + " maxProperties: 2\n" + " type: object\n" + " additionalProperties: false\n" + " deprecated: true\n" + " /one:\n" + " get:\n" + " operationId: requestBodySchemaPropertyNoSchema\n" + " requestBody:\n" + " content:\n" + " application/yaml:\n" + " schema:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " /two:\n" + " get:\n" + " operationId: requestBodySchemaPropertySchema\n" + " requestBody:\n" + " content:\n" + " application/yaml:\n" + " schema:\n" + " required:\n" + " - foo\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " /three:\n" + " get:\n" + " operationId: requestBodySchemaPropertySchemaArray\n" + " requestBody:\n" + " content:\n" + " application/yaml:\n" + " schema:\n" + " type: array\n" + " items:\n" + " required:\n" + " - foo\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/MultipleBaseBean\"\n" + "components:\n" + " schemas:\n" + " MultipleBaseBean:\n" + " type: object\n" + " properties:\n" + " beanType:\n" + " type: string\n" + " a:\n" + " type: integer\n" + " format: int32\n" + " b:\n" + " type: string\n" + " description: MultipleBaseBean\n" + " MultipleSub1Bean:\n" + " type: object\n" + " description: MultipleSub1Bean\n" + " allOf:\n" + " - $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " - type: object\n" + " properties:\n" + " c:\n" + " type: integer\n" + " format: int32\n" + " MultipleSub2Bean:\n" + " type: object\n" + " description: MultipleSub2Bean\n" + " allOf:\n" + " - $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " - type: object\n" + " properties:\n" + " d:\n" + " type: integer\n" + " format: int32\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Test Schema AdditionalProperties annotations") public void testSchemaAdditionalProperties() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(SchemaAdditionalPropertiesResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /arraySchemaImpl:\n" + " get:\n" + " operationId: arraySchemaImpl\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: object\n" + " additionalProperties:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " /fromtResponseType:\n" + " get:\n" + " operationId: fromtResponseType\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " additionalProperties:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " /schemaImpl:\n" + " get:\n" + " operationId: schemaImpl\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: object\n" + " additionalProperties:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " /schemaNotImpl:\n" + " get:\n" + " operationId: schemaNotImpl\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: object\n" + " additionalProperties:\n" + " $ref: \"#/components/schemas/Pet\"\n" + "components:\n" + " schemas:\n" + " Pet:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Test Schema AdditionalProperties annotations") public void testSchemaAdditionalPropertiesBoolean() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.ALL_OF); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(SchemaAdditionalPropertiesBooleanResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test:\n" + " get:\n" + " operationId: test\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + "components:\n" + " schemas:\n" + " Bar:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " Pet:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " allOf:\n" + " - additionalProperties:\n" + " $ref: \"#/components/schemas/Bar\"\n" + " - $ref: \"#/components/schemas/Bar\"\n" + " vbar:\n" + " allOf:\n" + " - additionalProperties: false\n" + " - $ref: \"#/components/schemas/Bar\"\n" + " additionalProperties: false\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test(description = "Test ArraySchema implementation annotations") public void testArraySchemaImplementation() { SwaggerConfiguration config = new SwaggerConfiguration().openAPI31(true).openAPI(new OpenAPI()); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(ArraySchemaImplementationResource.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " get:\n" + " operationId: test\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + "components:\n" + " schemas:\n" + " Pet:\n" + " type: object\n" + " properties:\n" + " cars:\n" + " type: array\n" + " items:\n" + " type: integer\n" + " format: int32\n" + " description: A house in a street\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test(description = "Responses schema resolved from return type") public void testResponseReturnType() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ResponseReturnTypeResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /sample/{id}:\n" + " get:\n" + " summary: Find by id\n" + " description: Find by id operation\n" + " operationId: find\n" + " parameters:\n" + " - name: id\n" + " in: path\n" + " description: ID\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " \"200\":\n" + " description: Ok\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/TestDTO\"\n" + " \"201\":\n" + " description: \"201\"\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/TestDTO\"\n" + " \"204\":\n" + " description: No Content\n" + " content:\n" + " application/json: {}\n" + " /sample/{id}/default:\n" + " get:\n" + " summary: Find by id (default)\n" + " description: Find by id operation (default)\n" + " operationId: findDefault\n" + " parameters:\n" + " - name: id\n" + " in: path\n" + " description: ID\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/TestDTO\"\n" + "components:\n" + " schemas:\n" + " TestDTO:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Responses Default Status") public void testResponseDefaultStatus() { SwaggerConfiguration config = new SwaggerConfiguration().defaultResponseCode("200"); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(DefaultResponseResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " operationId: test\n" + " responses:\n" + " \"200\":\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test public void test4412PathWildcards() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket4412Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/sws/{var}:\n" + " get:\n" + " operationId: getCart\n" + " parameters:\n" + " - name: var\n" + " in: path\n" + " required: true\n" + " schema:\n" + " pattern: .*\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " text/xml:\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test public void testOas31Petstore() { SwaggerConfiguration config = new SwaggerConfiguration().openAPI31(true).openAPI(new OpenAPI()); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(PetResource.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /pet:\n" + " put:\n" + " summary: Update an existing pet\n" + " operationId: updatePet\n" + " requestBody:\n" + " description: Pet object that needs to be added to the store\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " required: true\n" + " responses:\n" + " \"400\":\n" + " description: Invalid ID supplied\n" + " \"404\":\n" + " description: Pet not found\n" + " \"405\":\n" + " description: Validation exception\n" + " post:\n" + " summary: Add a new pet to the store\n" + " operationId: addPet\n" + " requestBody:\n" + " description: Pet object that needs to be added to the store\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " required: true\n" + " responses:\n" + " \"405\":\n" + " description: Invalid input\n" + " /pet/bodyid:\n" + " post:\n" + " summary: Add a new pet to the store passing an integer with generic parameter\n" + " annotation\n" + " operationId: addPetByInteger\n" + " requestBody:\n" + " description: Pet object that needs to be added to the store\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " application/xml:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " required: true\n" + " responses:\n" + " \"405\":\n" + " description: Invalid input\n" + " /pet/bodyidnoannotation:\n" + " post:\n" + " summary: Add a new pet to the store passing an integer without parameter annotation\n" + " operationId: addPetByIntegerNoAnnotation\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " application/xml:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " \"405\":\n" + " description: Invalid input\n" + " /pet/bodynoannotation:\n" + " post:\n" + " summary: Add a new pet to the store no annotation\n" + " operationId: addPetNoAnnotation\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " responses:\n" + " \"405\":\n" + " description: Invalid input\n" + " /pet/findByStatus:\n" + " get:\n" + " summary: Finds Pets by status\n" + " description: Multiple status values can be provided with comma separated strings\n" + " operationId: findPetsByStatus\n" + " parameters:\n" + " - name: status\n" + " in: query\n" + " description: Status values that need to be considered for filter\n" + " required: true\n" + " schema:\n" + " type: string\n" + " - name: skip\n" + " in: query\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " - name: limit\n" + " in: query\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " default:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " \"400\":\n" + " description: Invalid status value\n" + " /pet/findByTags:\n" + " get:\n" + " summary: Finds Pets by tags\n" + " description: \"Multiple tags can be provided with comma separated strings. Use\\\n" + " \\ tag1, tag2, tag3 for testing.\"\n" + " operationId: findPetsByTags\n" + " parameters:\n" + " - name: tags\n" + " in: query\n" + " description: Tags to filter by\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: Pets matching criteria\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " \"400\":\n" + " description: Invalid tag value\n" + " deprecated: true\n" + " /pet/{petId}:\n" + " get:\n" + " summary: Find pet by ID\n" + " description: Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate\n" + " API error conditions\n" + " operationId: getPetById\n" + " parameters:\n" + " - name: petId\n" + " in: path\n" + " description: ID of pet that needs to be fetched\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int64\n" + " responses:\n" + " default:\n" + " description: The pet\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " \"400\":\n" + " description: Invalid ID supplied\n" + " \"404\":\n" + " description: Pet not found\n" + "components:\n" + " schemas:\n" + " Bar:\n" + " type: object\n" + " deprecated: true\n" + " description: Bar\n" + " properties:\n" + " foo:\n" + " type: string\n" + " const: bar\n" + " bar:\n" + " type: integer\n" + " format: int32\n" + " exclusiveMaximum: 4\n" + " foobar:\n" + " type:\n" + " - string\n" + " - integer\n" + " format: int32\n" + " Category:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Category\n" + " Foo:\n" + " type: object\n" + " deprecated: true\n" + " description: Foo\n" + " properties:\n" + " foo:\n" + " type: string\n" + " const: foo\n" + " bar:\n" + " type: integer\n" + " format: int32\n" + " exclusiveMaximum: 2\n" + " foobar:\n" + " type:\n" + " - string\n" + " - object\n" + " format: int32\n" + " IfSchema:\n" + " type: object\n" + " deprecated: true\n" + " description: if schema\n" + " properties:\n" + " foo:\n" + " type: string\n" + " const: foo\n" + " bar:\n" + " type: integer\n" + " format: int32\n" + " exclusiveMaximum: 2\n" + " foobar:\n" + " type:\n" + " - string\n" + " - object\n" + " format: int32\n" + " Pet:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " category:\n" + " $ref: \"#/components/schemas/Category\"\n" + " name:\n" + " type: string\n" + " photoUrls:\n" + " type: array\n" + " items:\n" + " type: string\n" + " xml:\n" + " name: photoUrl\n" + " xml:\n" + " wrapped: true\n" + " tags:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Tag\"\n" + " xml:\n" + " wrapped: true\n" + " status:\n" + " type: string\n" + " if:\n" + " $ref: \"#/components/schemas/IfSchema\"\n" + " $id: idtest\n" + " description: pet status in the store\n" + " enum:\n" + " - \"available,pending,sold\"\n" + " xml:\n" + " name: Pet\n" + " Tag:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " annotated:\n" + " type: object\n" + " $ref: \"#/components/schemas/Category\"\n" + " description: child description\n" + " properties:\n" + " foo:\n" + " $ref: \"#/components/schemas/Foo\"\n" + " bar:\n" + " $ref: \"#/components/schemas/Bar\"\n" + " xml:\n" + " name: Tag\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void test31RefSiblings() { SwaggerConfiguration config = new SwaggerConfiguration().openAPI31(true).openAPI(new OpenAPI()); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(TagResource.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /tag/tag:\n" + " get:\n" + " operationId: getTag\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SimpleTag\"\n" + "components:\n" + " schemas:\n" + " Foo:\n" + " type: object\n" + " deprecated: true\n" + " description: Foo\n" + " properties:\n" + " foo:\n" + " type: string\n" + " const: foo\n" + " bar:\n" + " type: integer\n" + " format: int32\n" + " exclusiveMaximum: 2\n" + " foobar:\n" + " type:\n" + " - string\n" + " - object\n" + " format: int32\n" + " SimpleTag:\n" + " type: object\n" + " properties:\n" + " annotated:\n" + " type: object\n" + " $ref: \"#/components/schemas/SimpleCategory\"\n" + " description: child description\n" + " properties:\n" + " foo:\n" + " $ref: \"#/components/schemas/Foo\"\n" + " SimpleCategory: {}\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void testSiblings() { Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); OpenAPI openAPI = reader.read(SiblingsResource.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " get:\n" + " operationId: getCart\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + "components:\n" + " schemas:\n" + " Category:\n" + " type: object\n" + " description: parent\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " Pet:\n" + " type: object\n" + " description: Pet\n" + " properties:\n" + " category:\n" + " $ref: \"#/components/schemas/Category\"\n" + " description: child\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void testSiblingsOnResource() { Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); OpenAPI openAPI = reader.read(SiblingsResourceSimple.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " get:\n" + " operationId: getCart\n" + " responses:\n" + " \"300\":\n" + " description: aaa\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet\n" + " readOnly: true\n" + " /test/impl:\n" + " get:\n" + " operationId: getCartImpl\n" + " responses:\n" + " \"300\":\n" + " description: aaa\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet\n" + " readOnly: true\n" + "components:\n" + " schemas:\n" + " PetSimple:\n" + " description: Pet\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void testSiblingsOnResourceResponse() { Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); OpenAPI openAPI = reader.read(SiblingsResourceResponse.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " get:\n" + " operationId: getCart\n" + " responses:\n" + " \"300\":\n" + " description: aaa\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet\n" + " readOnly: true\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet xml\n" + " readOnly: true\n" + " /test/impl:\n" + " get:\n" + " operationId: getCartImpl\n" + " responses:\n" + " \"300\":\n" + " description: aaa\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet\n" + " readOnly: true\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet xml\n" + " readOnly: true\n" + "components:\n" + " schemas:\n" + " PetSimple:\n" + " description: Pet\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void testSiblingsOnResourceRequestBody() { Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); OpenAPI openAPI = reader.read(SiblingsResourceRequestBody.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /test/bodyimpl:\n" + " get:\n" + " operationId: getBodyImpl\n" + " requestBody:\n" + " description: aaa\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet\n" + " writeOnly: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/bodyimplparam:\n" + " get:\n" + " operationId: getBodyImplParam\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet\n" + " writeOnly: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " PetSimple:\n" + " description: Pet\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void testSiblingsOnResourceRequestBodyMultiple() { Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); OpenAPI openAPI = reader.read(SiblingsResourceRequestBodyMultiple.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /test/bodyimpl:\n" + " get:\n" + " operationId: getBodyImpl\n" + " requestBody:\n" + " description: aaa\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet\n" + " writeOnly: true\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet xml\n" + " writeOnly: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/bodyimplparam:\n" + " get:\n" + " operationId: getBodyImplParam\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet\n" + " writeOnly: true\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet xml\n" + " writeOnly: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/bodyparam:\n" + " get:\n" + " operationId: getBodyParam\n" + " requestBody:\n" + " description: test\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet\n" + " writeOnly: true\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/PetSimple\"\n" + " description: resource pet xml\n" + " writeOnly: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " PetSimple:\n" + " description: Pet\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void testSiblingsOnProperty() { Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); Set> classes = new HashSet<>(Arrays.asList(SiblingPropResource.class, WebHookResource.class)); OpenAPI openAPI = reader.read(classes); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /pet:\n" + " put:\n" + " tags:\n" + " - pet\n" + " summary: Update an existing pet\n" + " operationId: updatePet\n" + " requestBody:\n" + " description: Pet object that needs to be updated in the store\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " description: A Pet in JSON Format\n" + " required:\n" + " - id\n" + " writeOnly: true\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " description: A Pet in XML Format\n" + " required:\n" + " - id\n" + " writeOnly: true\n" + " required: true\n" + " responses:\n" + " \"200\":\n" + " description: Successful operation\n" + " content:\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " description: A Pet in XML Format\n" + " readOnly: true\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " description: A Pet in JSON Format\n" + " readOnly: true\n" + " \"400\":\n" + " description: Invalid ID supplied\n" + " \"404\":\n" + " description: Pet not found\n" + " \"405\":\n" + " description: Validation exception\n" + " security:\n" + " - petstore_auth:\n" + " - write:pets\n" + " - read:pets\n" + " - mutual_tls: []\n" + "components:\n" + " schemas:\n" + " Category:\n" + " type: object\n" + " description: parent\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " Pet:\n" + " type: object\n" + " description: Pet\n" + " properties:\n" + " category:\n" + " $ref: \"#/components/schemas/Category\"\n" + " description: child\n" + "webhooks:\n" + " newPet:\n" + " post:\n" + " requestBody:\n" + " description: Information about a new pet in the system\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " description: Webhook Pet\n" + " responses:\n" + " \"200\":\n" + " description: Return a 200 status to indicate that the data was received\n" + " successfully\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void testMisc31() { Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); Set> classes = new HashSet<>(Arrays.asList(Misc31Resource.class)); OpenAPI openAPI = reader.read(classes); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /pet:\n" + " put:\n" + " operationId: updatePet\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/ModelWithOAS31Stuff\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/ModelWithOAS31Stuff\"\n" + "components:\n" + " schemas:\n" + " ModelWithOAS31Stuff:\n" + " type: object\n" + " $comment: Random comment at schema level\n" + " $id: http://yourdomain.com/schemas/myschema.json\n" + " description: this is model for testing OAS 3.1 resolving\n" + " properties:\n" + " randomList:\n" + " type: array\n" + " contains:\n" + " type: string\n" + " items:\n" + " type: string\n" + " maxContains: 10\n" + " minContains: 1\n" + " prefixItems:\n" + " - type: string\n" + " unevaluatedItems:\n" + " type: number\n" + " status:\n" + " type:\n" + " - string\n" + " - number\n" + " intValue:\n" + " type: integer\n" + " format: int32\n" + " $anchor: intValue\n" + " $comment: comment at schema property level\n" + " exclusiveMaximum: 100\n" + " exclusiveMinimum: 1\n" + " text:\n" + " type: string\n" + " contentEncoding: plan/text\n" + " contentMediaType: base64\n" + " encodedString:\n" + " type: string\n" + " contentMediaType: application/jwt\n" + " contentSchema:\n" + " $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " address:\n" + " $ref: \"#/components/schemas/Address\"\n" + " client:\n" + " type: string\n" + " dependentSchemas:\n" + " creditCard:\n" + " $ref: \"#/components/schemas/CreditCard\"\n" + " MultipleBaseBean:\n" + " type: object\n" + " description: MultipleBaseBean\n" + " properties:\n" + " beanType:\n" + " type: string\n" + " a:\n" + " type: integer\n" + " format: int32\n" + " b:\n" + " type: string\n" + " MultipleSub1Bean:\n" + " allOf:\n" + " - $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " - type: object\n" + " properties:\n" + " c:\n" + " type: integer\n" + " format: int32\n" + " description: MultipleSub1Bean\n" + " MultipleSub2Bean:\n" + " allOf:\n" + " - $ref: \"#/components/schemas/MultipleBaseBean\"\n" + " - type: object\n" + " properties:\n" + " d:\n" + " type: integer\n" + " format: int32\n" + " description: MultipleSub2Bean\n" + " Address:\n" + " type: object\n" + " if:\n" + " $ref: \"#/components/schemas/AnnotatedCountry\"\n" + " then:\n" + " $ref: \"#/components/schemas/PostalCodeNumberPattern\"\n" + " else:\n" + " $ref: \"#/components/schemas/PostalCodePattern\"\n" + " dependentRequired:\n" + " street:\n" + " - country\n" + " properties:\n" + " street:\n" + " type: string\n" + " country:\n" + " type: string\n" + " enum:\n" + " - United States of America\n" + " - Canada\n" + " propertyNames:\n" + " pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\"\n" + " AnnotatedCountry:\n" + " type: object\n" + " properties:\n" + " country:\n" + " type: object\n" + " const: United States\n" + " CreditCard:\n" + " type: object\n" + " properties:\n" + " billingAddress:\n" + " type: string\n" + " PostalCodeNumberPattern:\n" + " type: object\n" + " properties:\n" + " postalCode:\n" + " type: object\n" + " pattern: \"[0-9]{5}(-[0-9]{4})?\"\n" + " PostalCodePattern:\n" + " type: object\n" + " properties:\n" + " postalCode:\n" + " type: object\n" + " pattern: \"[A-Z][0-9][A-Z] [0-9][A-Z][0-9]\"\n" + " PropertyNamesPattern:\n" + " pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\"\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void test4446CyclicProp() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket4446Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/test:\n" + " get:\n" + " operationId: getCart\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/MyPojo\"\n" + "components:\n" + " schemas:\n" + " MyPojo:\n" + " type: object\n" + " properties:\n" + " someStrings:\n" + " type: array\n" + " items:\n" + " type: string\n" + " morePojos:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/MyPojo\"\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test public void testParameterMaximumValue() { Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).openAPI31(true)); OpenAPI openAPI = reader.read(ParameterMaximumValueResource.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /test/{petId}:\n" + " get:\n" + " operationId: getPetById\n" + " parameters:\n" + " - name: petId\n" + " in: path\n" + " description: ID of pet that needs to be fetched\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int64\n" + " exclusiveMaximum: 10\n" + " exclusiveMinimum: 1\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test public void test4483Response() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket4483Resource.class); String yaml = "openapi: 3.0.1\n" + "tags:\n" + "- name: Dummy\n" + " description: Dummy resource for testing setup\n" + "paths:\n" + " /test:\n" + " get:\n" + " tags:\n" + " - Dummy\n" + " description: Dummy GET\n" + " operationId: dummy\n" + " responses:\n" + " \"401\":\n" + " description: Authentication is required\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/LocalizedError\"\n" + " \"200\":\n" + " description: test\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: object\n" + " additionalProperties:\n" + " type: boolean\n" + " /test/opresp:\n" + " get:\n" + " tags:\n" + " - Dummy\n" + " operationId: dummyopresp\n" + " responses:\n" + " \"401\":\n" + " description: Authentication is required\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/LocalizedError\"\n" + " \"200\":\n" + " description: Dummy GET opresp\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: object\n" + " additionalProperties:\n" + " type: boolean\n" + " /test/oprespnodesc:\n" + " get:\n" + " tags:\n" + " - Dummy\n" + " operationId: oprespnodesc\n" + " responses:\n" + " \"401\":\n" + " description: Authentication is required\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/LocalizedError\"\n" + "components:\n" + " schemas:\n" + " LocalizedError:\n" + " type: object\n" + " properties:\n" + " code:\n" + " type: string\n" + " message:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "openAPIVersion") public void testOpenAPIVersion() { SwaggerConfiguration config = new SwaggerConfiguration().openAPIVersion("3.0.4"); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(DefaultResponseResource.class); String yaml = "openapi: 3.0.4\n" + "paths:\n" + " /:\n" + " get:\n" + " operationId: test\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } @Test(description = "Constraints annotations with groups - Inline") public void testTicket4804Inline() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration().schemaResolution(Schema.SchemaResolution.INLINE); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4804Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/barcart:\n" + " put:\n" + " operationId: barCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " required:\n" + " - notNullcartDetails\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/foocart:\n" + " put:\n" + " operationId: fooCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " required:\n" + " - cartDetails\n" + " - notNullcartDetails\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/createcart:\n" + " post:\n" + " operationId: postCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " required:\n" + " - notNullcartDetails\n" + " - pageSize\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " required:\n" + " - description\n" + " - name\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " required:\n" + " - description\n" + " - name\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/updatecart:\n" + " put:\n" + " operationId: putCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " required:\n" + " - notNullcartDetails\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Cart:\n" + " required:\n" + " - notNullcartDetails\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " CartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test(description = "Constraints annotations with groups - Default") public void testTicket4804Default() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration(); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4804Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/barcart:\n" + " put:\n" + " operationId: barCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/foocart:\n" + " put:\n" + " operationId: fooCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/createcart:\n" + " post:\n" + " operationId: postCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/updatecart:\n" + " put:\n" + " operationId: putCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Cart:\n" + " required:\n" + " - notNullcartDetails\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " $ref: \"#/components/schemas/CartDetails\"\n" + " notNullcartDetails:\n" + " $ref: \"#/components/schemas/CartDetails\"\n" + " CartDetails:\n" + " required:\n" + " - description\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test(description = "Constraints annotations with groups - Default NotBlank") public void testTicket4804DefaultNotBlank() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration(); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4804NotBlankResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/barcart:\n" + " put:\n" + " operationId: barCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/createcart:\n" + " post:\n" + " operationId: postCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/updatecart:\n" + " put:\n" + " operationId: putCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Cart:\n" + " required:\n" + " - notNullcartDetails\n" + " - pageSizes\n" + " type: object\n" + " properties:\n" + " pageSizes:\n" + " type: array\n" + " items:\n" + " type: integer\n" + " format: int32\n" + " notNullcartDetails:\n" + " $ref: \"#/components/schemas/CartDetails\"\n" + " CartDetails:\n" + " required:\n" + " - description\n" + " - name\n" + " type: object\n" + " properties:\n" + " name:\n" + " minLength: 1\n" + " type: string\n" + " description:\n" + " minItems: 1\n" + " type: array\n" + " items:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test(description = "Constraints annotations with groups - Always") public void testTicket4804Always() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration().groupsValidationStrategy(Configuration.GroupsValidationStrategy.ALWAYS); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4804Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/barcart:\n" + " put:\n" + " operationId: barCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/foocart:\n" + " put:\n" + " operationId: fooCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/createcart:\n" + " post:\n" + " operationId: postCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/updatecart:\n" + " put:\n" + " operationId: putCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Cart:\n" + " required:\n" + " - cartDetails\n" + " - notNullcartDetails\n" + " - pageSize\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " $ref: \"#/components/schemas/CartDetails\"\n" + " notNullcartDetails:\n" + " $ref: \"#/components/schemas/CartDetails\"\n" + " CartDetails:\n" + " required:\n" + " - description\n" + " - name\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test(description = "Constraints annotations with groups - Never") public void testTicket4804Never() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration().groupsValidationStrategy(Configuration.GroupsValidationStrategy.NEVER); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4804Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/barcart:\n" + " put:\n" + " operationId: barCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/foocart:\n" + " put:\n" + " operationId: fooCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/createcart:\n" + " post:\n" + " operationId: postCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/updatecart:\n" + " put:\n" + " operationId: putCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Cart\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Cart:\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " $ref: \"#/components/schemas/CartDetails\"\n" + " notNullcartDetails:\n" + " $ref: \"#/components/schemas/CartDetails\"\n" + " CartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test(description = "Constraints annotations with groups - NeverNoContext") public void testTicket4804NeverNoContext() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration() .groupsValidationStrategy(Configuration.GroupsValidationStrategy.NEVER_IF_NO_CONTEXT) .schemaResolution(Schema.SchemaResolution.INLINE); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4804Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/barcart:\n" + " put:\n" + " operationId: barCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/foocart:\n" + " put:\n" + " operationId: fooCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " required:\n" + " - cartDetails\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/createcart:\n" + " post:\n" + " operationId: postCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " required:\n" + " - pageSize\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " required:\n" + " - name\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " required:\n" + " - name\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/updatecart:\n" + " put:\n" + " operationId: putCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Cart:\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " CartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test(description = "Constraints annotations with groups - Processor") public void testTicket4804Processor() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration() .validatorProcessorClass(Ticket4804ProcessorResource.CustomValidatorProcessor.class.getName()) .schemaResolution(Schema.SchemaResolution.INLINE); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4804ProcessorResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/barcart:\n" + " put:\n" + " operationId: barCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/foocart:\n" + " put:\n" + " operationId: fooCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/createcart:\n" + " post:\n" + " operationId: postCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/updatecart:\n" + " put:\n" + " operationId: putCart\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " required:\n" + " - cartDetails\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Cart:\n" + " required:\n" + " - cartDetails\n" + " type: object\n" + " properties:\n" + " pageSize:\n" + " type: integer\n" + " format: int32\n" + " cartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " notNullcartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n" + " CartDetails:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: string\n" + " description:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test public void shouldIncludeOnlyNonGroupedJakartaValidatedFieldsAsMandatoryByDefault() { ModelConverters.reset(); ResolvedSchema schema = ModelConverters.getInstance(false).resolveAsResolvedSchema(new AnnotatedType().type(Ticket4804CustomClass.class)); String expectedYaml = "schema:\n" + " required:\n" + " - nonGroupValidatedField\n" + " type: object\n" + " properties:\n" + " nonGroupValidatedField:\n" + " type: string\n" + " singleGroupValidatedField:\n" + " type: integer\n" + " format: int32\n" + " multipleGroupValidatedField:\n" + " type: number\n" + " otherGroupValidatedField:\n" + " type: string\n" + " singleGroupValidatedField2:\n" + " type: string\n" + "referencedSchemas:\n" + " Ticket4804CustomClass:\n" + " required:\n" + " - nonGroupValidatedField\n" + " type: object\n" + " properties:\n" + " nonGroupValidatedField:\n" + " type: string\n" + " singleGroupValidatedField:\n" + " type: integer\n" + " format: int32\n" + " multipleGroupValidatedField:\n" + " type: number\n" + " otherGroupValidatedField:\n" + " type: string\n" + " singleGroupValidatedField2:\n" + " type: string\n"; SerializationMatchers.assertEqualsToYaml(schema, expectedYaml); ModelConverters.reset(); } @Test(description = "test schema.minLength applied") public void testTicket4859() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration(); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4859Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/minlength:\n" + " put:\n" + " operationId: minlength\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Minlength\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Minlength:\n" + " required:\n" + " - name\n" + " type: object\n" + " properties:\n" + " name:\n" + " maxLength: 19\n" + " minLength: 12\n" + " type: string\n" + " example: \"4242424242424242\"\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } @Test(description = "test default value type") public void testTicket4879() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration().openAPI31(true); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4879Resource.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /test/test:\n" + " put:\n" + " operationId: test\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/DefaultClass\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/testDefaultValueAnnotation:\n" + " get:\n" + " operationId: testDefault\n" + " parameters:\n" + " - name: myBool\n" + " in: query\n" + " schema:\n" + " type: boolean\n" + " default: true\n" + " - name: myInt\n" + " in: query\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " default: 1\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /test/testsize:\n" + " get:\n" + " operationId: testSize\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n" + " maxItems: 100\n" + " minItems: 1\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " DefaultClass:\n" + " type: object\n" + " properties:\n" + " name:\n" + " type: boolean\n" + " default: true\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); ModelConverters.reset(); } @Test(description = "test explode FALSE") public void testTicket4065() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration(); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4065Resource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /bar:\n" + " get:\n" + " operationId: test\n" + " parameters:\n" + " - name: blub\n" + " in: query\n" + " explode: false\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: integer\n" + " format: int64\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); ModelConverters.reset(); } @Test(description = "Extensions Tests OAS 3.1") public void testExtensionsOAS31() { SwaggerConfiguration config = new SwaggerConfiguration().openAPI31(true); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4850Resource.class); assertNotNull(openAPI); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /bar:\n" + " get:\n" + " operationId: test\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/ExtensionsResource\"\n" + "components:\n" + " schemas:\n" + " ExtensionsResource:\n" + " description: ExtensionsResource\n" + " x-user:\n" + " name: Josh\n" + " user-extensions:\n" + " lastName: Hart\n" + " address: House"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } @Test(description = "Test model resolution for global path parameters with openAPI 3.1") public void testTicket4878() { ModelConverters.reset(); SwaggerConfiguration config = new SwaggerConfiguration().openAPI31(true); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4878Resource.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /{globalPathParam}/{localPathParam}:\n" + " get:\n" + " operationId: getMethod\n" + " parameters:\n" + " - name: globalPathParam\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " $comment: 3.1 property for global path param\n" + " - name: localPathParam\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " $comment: 3.1 property for local path param\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); ModelConverters.reset(); } @Test(description = "Test model resolution for global path parameters with openAPI 3.1") public void testTicket4907() { ModelConverters.reset(); // openAPI31 true and no other config SwaggerConfiguration config = new SwaggerConfiguration().openAPI31(true); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket4878Resource.class); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /{globalPathParam}/{localPathParam}:\n" + " get:\n" + " operationId: getMethod\n" + " parameters:\n" + " - name: globalPathParam\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " $comment: 3.1 property for global path param\n" + " - name: localPathParam\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " $comment: 3.1 property for local path param\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); // openAPI31 true and openAPI set config.setOpenAPI(new OpenAPI().openapi("3.1.1")); reader = new Reader(config); openAPI = reader.read(Ticket4878Resource.class); yaml = "openapi: 3.1.1\n" + "paths:\n" + " /{globalPathParam}/{localPathParam}:\n" + " get:\n" + " operationId: getMethod\n" + " parameters:\n" + " - name: globalPathParam\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " $comment: 3.1 property for global path param\n" + " - name: localPathParam\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " $comment: 3.1 property for local path param\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); // openAPI31 true and openAPIVersion set config.setOpenAPI(null); config.setOpenAPIVersion("3.1.1"); reader = new Reader(config); openAPI = reader.read(Ticket4878Resource.class); yaml = "openapi: 3.1.1\n" + "paths:\n" + " /{globalPathParam}/{localPathParam}:\n" + " get:\n" + " operationId: getMethod\n" + " parameters:\n" + " - name: globalPathParam\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " $comment: 3.1 property for global path param\n" + " - name: localPathParam\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " $comment: 3.1 property for local path param\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); ModelConverters.reset(); } @Test(description = "array property metadata is resolved from ArraySchema.arraySchema, items metadata from ArraySchema.schema") public void test4341ArraySchemaOtherAttributes() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Ticket4341Resource.class); System.out.println(Json.pretty(openAPI)); Schema userSchema = openAPI.getComponents().getSchemas().get("User"); assertNotNull(userSchema, "User schema should be present"); @SuppressWarnings("unchecked") Map properties = userSchema.getProperties(); assertNotNull(properties, "User properties should not be null"); Schema metadataArray = properties.get("metadataArray"); assertNotNull(metadataArray, "metadataArray property should be present"); assertTrue(metadataArray instanceof ArraySchema, "metadataArray should be an ArraySchema"); // Property-level assertions assertEquals( metadataArray.getDescription(), "array-level description", "Array property description should come from arraySchema, not items schema" ); assertEquals( metadataArray.getDeprecated(), Boolean.TRUE, "Array property deprecated should come from arraySchema" ); assertEquals( metadataArray.getReadOnly(), Boolean.TRUE, "Array property readOnly should be true from arraySchema.accessMode=READ_ONLY" ); assertNotEquals( metadataArray.getWriteOnly(), Boolean.TRUE, "Array property writeOnly should not be true when accessMode=READ_ONLY" ); // Item-level assertions ArraySchema metadataArraySchema = (ArraySchema) metadataArray; Schema items = metadataArraySchema.getItems(); assertNotNull(items, "Items schema should not be null"); assertEquals( items.getDescription(), "item-level description", "Items description should come from schema element of @ArraySchema" ); assertNotEquals( items.getDeprecated(), Boolean.TRUE, "Items deprecated should not be true when schema.deprecated=false" ); assertEquals( items.getWriteOnly(), Boolean.TRUE, "Items writeOnly should be true from schema.accessMode=WRITE_ONLY" ); assertNotEquals( items.getReadOnly(), Boolean.TRUE, "Items readOnly should not be true when accessMode=WRITE_ONLY" ); assertEquals( items.getFormat(), "email", "Items format should come from schema.format" ); } @Test void testTicket5017() { ModelResolver.enumsAsRef = true; SwaggerConfiguration config = new SwaggerConfiguration().openAPI31(true); Reader reader = new Reader(config); OpenAPI openAPI = reader.read(Ticket5017Resource.class); OpenAPISpecFilter filterImpl = new RemoveUnusedSchemasOAS31Filter(); SpecFilter f = new SpecFilter(); openAPI = f.filter(openAPI, filterImpl, null, null, null); String yaml = "openapi: 3.1.0\n" + "paths:\n" + " /test:\n" + " get:\n" + " operationId: myMethod\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Example\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " Example:\n" + " type: object\n" + " properties:\n" + " myMap:\n" + " type: object\n" + " additionalProperties:\n" + " type: string\n" + " propertyNames:\n" + " $ref: \"#/components/schemas/MyEnum\"\n" + " MyEnum:\n" + " type: string\n" + " enum:\n" + " - FOO\n" + " - BAR\n"; SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } static class RemoveUnusedSchemasOAS31Filter extends AbstractSpecFilter { @Override public boolean isRemovingUnreferencedDefinitions() { return true; } @Override public boolean isOpenAPI31Filter() { return true; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfRefTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResource; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class SchemaResolutionAllOfRefTest { @Test public void testSchemaResolutionAllOfRef() { ModelConverters.reset(); Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.ALL_OF_REF)); OpenAPI openAPI = reader.read(SchemaResolutionResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/inlineSchemaFirst:\n" + " get:\n" + " operationId: inlineSchemaFirst\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/InlineSchemaFirst\"\n" + " /test/inlineSchemaSecond:\n" + " get:\n" + " operationId: inlineSchemaSecond\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " description: InlineSchemaSecond API\n" + " allOf:\n" + " - $ref: \"#/components/schemas/InlineSchemaSecond\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/InlineSchemaSecond\"\n" + "components:\n" + " schemas:\n" + " InlineSchemaFirst:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " description: InlineSchemaFirst property 1\n" + " nullable: true\n" + " allOf:\n" + " - $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + " property2:\n" + " description: ' InlineSchemaFirst property 2'\n" + " example: example 2\n" + " allOf:\n" + " - $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + " InlineSchemaPropertyFirst:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " InlineSchemaPropertySecond:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " $ref: \"#/components/schemas/InlineSchemaSimple\"\n" + " description: propertysecond\n" + " example: examplesecond\n" + " InlineSchemaPropertySimple:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " InlineSchemaSecond:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " description: InlineSchemaSecond property 1\n" + " nullable: true\n" + " allOf:\n" + " - $ref: \"#/components/schemas/InlineSchemaPropertySecond\"\n" + " property2:\n" + " description: InlineSchemaSecond property 2\n" + " example: InlineSchemaSecond example 2\n" + " allOf:\n" + " - $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + " InlineSchemaSimple:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " description: property 1\n" + " allOf:\n" + " - $ref: \"#/components/schemas/InlineSchemaPropertySimple\"\n" + " property2:\n" + " description: property 2\n" + " example: example\n" + " allOf:\n" + " - $ref: \"#/components/schemas/InlineSchemaPropertySimple\"\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAllOfTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResourceSimple; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class SchemaResolutionAllOfTest { @Test public void testSchemaResolutionAllOf() { Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.ALL_OF)); OpenAPI openAPI = reader.read(SchemaResolutionResourceSimple.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/inlineSchemaFirst:\n" + " get:\n" + " operationId: inlineSchemaFirst\n" + " responses:\n" + " default:\n" + " description: InlineSchemaFirst Response API\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/InlineSchemaFirst\"\n" + " /test/inlineSchemaSecond:\n" + " get:\n" + " operationId: inlineSchemaFirst_1\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " allOf:\n" + " - description: InlineSchemaSecond API\n" + " - $ref: \"#/components/schemas/InlineSchemaFirst\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " InlineSchemaFirst:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + " InlineSchemaPropertyFirst:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " nullable: true\n" + " example: example\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionAnnotationTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionAnnotatedResource; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.OpenAPI; import org.testng.annotations.Test; public class SchemaResolutionAnnotationTest { @Test public void testSchemaResolutionAnnotation() { ModelConverters.reset(); Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI())); OpenAPI openAPI = reader.read(SchemaResolutionAnnotatedResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/inlineSchemaFirst:\n" + " get:\n" + " operationId: inlineSchemaFirst\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/InlineSchemaFirst\"\n" + " /test/inlineSchemaSecond:\n" + " get:\n" + " operationId: inlineSchemaSecond\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " $ref: \"#/components/schemas/InlineSchemaPropertySecond\"\n" + " property2:\n" + " $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + " description: InlineSchemaSecond API\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/InlineSchemaSecond\"\n" + "components:\n" + " schemas:\n" + " InlineSchemaFirst:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " description: InlineSchemaFirst property 1\n" + " nullable: true\n" + " allOf:\n" + " - $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " InlineSchemaPropertyFirst:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " InlineSchemaPropertySecond:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " $ref: \"#/components/schemas/InlineSchemaSimple\"\n" + " description: propertysecond\n" + " nullable: true\n" + " example: examplesecond\n" + " InlineSchemaPropertySimple:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " InlineSchemaSecond:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " $ref: \"#/components/schemas/InlineSchemaPropertySecond\"\n" + " property2:\n" + " $ref: \"#/components/schemas/InlineSchemaPropertyFirst\"\n" + " description: InlineSchemaSecond API\n" + " InlineSchemaSimple:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " property2:\n" + " description: property 2\n" + " example: example\n" + " allOf:\n" + " - $ref: \"#/components/schemas/InlineSchemaPropertySimple\"\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/SchemaResolutionInlineTest.java ================================================ package io.swagger.v3.jaxrs2; import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; import io.swagger.v3.jaxrs2.schemaResolution.SchemaResolutionResource; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.Test; public class SchemaResolutionInlineTest { @Test public void testSchemaResolutionInline() { ModelConverters.reset(); Reader reader = new Reader(new SwaggerConfiguration().openAPI(new OpenAPI()).schemaResolution(Schema.SchemaResolution.INLINE)); OpenAPI openAPI = reader.read(SchemaResolutionResource.class); String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /test/inlineSchemaFirst:\n" + " get:\n" + " operationId: inlineSchemaFirst\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: InlineSchemaFirst property 1\n" + " nullable: true\n" + " example: example\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: ' InlineSchemaFirst property 2'\n" + " example: example 2\n" + " /test/inlineSchemaSecond:\n" + " get:\n" + " operationId: inlineSchemaSecond\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n" + " description: InlineSchemaSecond property 1\n" + " nullable: true\n" + " example: examplesecond\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: InlineSchemaSecond property 2\n" + " example: InlineSchemaSecond example 2\n" + " description: InlineSchemaSecond API\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n" + " description: InlineSchemaSecond property 1\n" + " nullable: true\n" + " example: examplesecond\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: InlineSchemaSecond property 2\n" + " example: InlineSchemaSecond example 2\n" + "components:\n" + " schemas:\n" + " InlineSchemaFirst:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: InlineSchemaFirst property 1\n" + " nullable: true\n" + " example: example\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: ' InlineSchemaFirst property 2'\n" + " example: example 2\n" + " InlineSchemaPropertyFirst:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " InlineSchemaPropertySecond:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n" + " description: propertysecond\n" + " nullable: true\n" + " example: examplesecond\n" + " InlineSchemaPropertySimple:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property\n" + " example: example\n" + " InlineSchemaSecond:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string\n" + " propertySecond1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n" + " description: InlineSchemaSecond property 1\n" + " nullable: true\n" + " example: examplesecond\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: InlineSchemaSecond property 2\n" + " example: InlineSchemaSecond example 2\n" + " description: InlineSchemaSecond API\n" + " InlineSchemaSimple:\n" + " type: object\n" + " properties:\n" + " property1:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 1\n" + " property2:\n" + " type: object\n" + " properties:\n" + " bar:\n" + " type: string\n" + " description: property 2\n" + " example: example\n\n"; SerializationMatchers.assertEqualsToYaml(openAPI, yaml); ModelConverters.reset(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/AbstractAnnotationTest.java ================================================ package io.swagger.v3.jaxrs2.annotations; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.jaxrs2.Reader; import io.swagger.v3.jaxrs2.matchers.SerializationMatchers; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.models.OpenAPI; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import static org.testng.Assert.fail; public abstract class AbstractAnnotationTest { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAnnotationTest.class); public String readIntoYaml(final Class cls) { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(cls); try { Yaml.mapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); // parse JSON JsonNode jsonNodeTree = Yaml.mapper().readTree(Yaml.mapper().writeValueAsString(openAPI)); // return it as YAML return Yaml.mapper().writeValueAsString(jsonNodeTree); } catch (Exception e) { return "Empty YAML"; } } public void compareToYamlFile(final Class cls, String source){ final String file = source + cls.getSimpleName() + ".yaml"; try { compareAsYaml(cls, getOpenAPIAsString(file)); } catch (IOException e) { LOGGER.error("Failed to compare class {} with YAML resource {}", cls.getName(), file, e); fail(); } } public void compareAsYaml(final Class cls, final String yaml) throws IOException { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(cls); SerializationMatchers.assertEqualsToYaml(openAPI, yaml); } public void compareAsYaml(final String actualYaml, final String expectedYaml) throws IOException { SerializationMatchers.assertEqualsToYaml(Yaml.mapper().readValue(actualYaml, OpenAPI.class), expectedYaml); } public void compareAsJson(final String actualJson, final String expectedJson) throws IOException { SerializationMatchers.assertEqualsToJson(Yaml.mapper().readValue(actualJson, OpenAPI.class), expectedJson); } protected String getOpenAPIAsString(final String file) throws IOException { InputStream in = null; try { in = getClass().getClassLoader().getResourceAsStream(file); return IOUtils.toString(in, StandardCharsets.UTF_8); } finally { IOUtils.closeQuietly(in); } } public void compareAsYamlOAS31(final Class cls, final String yaml) throws IOException { Reader reader = new Reader(new SwaggerConfiguration() .openAPI(new OpenAPI()) .openAPI31(true)); OpenAPI openAPI = reader.read(cls); SerializationMatchers.assertEqualsToYaml31(openAPI, yaml); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/callbacks/CallbackTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.callbacks; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.testng.annotations.Test; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import static org.testng.Assert.assertEquals; public class CallbackTest extends AbstractAnnotationTest { @Test public void testSimpleCallback() { String openApiYAML = readIntoYaml(SimpleCallback.class); int start = openApiYAML.indexOf("/test:"); int end = openApiYAML.length() - 1; String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "/test:\n" + " post:\n" + " description: \"subscribes a client to updates relevant to the requestor's account,\\\n" + " \\ as identified by the input token. The supplied url will be used as the\\\n" + " \\ delivery address for response payloads\"\n" + " operationId: subscribe\n" + " parameters:\n" + " - name: x-auth-token\n" + " in: header\n" + " schema:\n" + " type: string\n" + " description: the authentication token provided after initially authenticating\n" + " to the application\n" + " readOnly: true\n" + " - name: url\n" + " in: query\n" + " schema:\n" + " type: string\n" + " description: the URL to call with response data\n" + " readOnly: true\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " callbacks:\n" + " subscription:\n" + " http://$request.query.url:\n" + " post:\n" + " description: payload data will be sent\n" + " parameters:\n" + " - name: subscriptionId\n" + " in: path\n" + " required: true\n" + " schema:\n" + " maximum: 34\n" + " minimum: 2\n" + " type: string\n" + " description: the generated UUID\n" + " format: uuid\n" + " readOnly: true\n" + " responses:\n" + " \"200\":\n" + " description: Return this code if the callback was received and processed\n" + " successfully\n" + " \"205\":\n" + " description: Return this code to unsubscribe from future data updates\n" + " default:\n" + " description: All other response codes will disable this callback\n" + " subscription\n" + "components:\n" + " schemas:\n" + " SubscriptionResponse:\n" + " type: object\n" + " properties:\n" + " subscriptionId:\n" + " type: string"; assertEquals(extractedYAML, expectedYAML); } static class SimpleCallback { @Path("/test") @POST @Callback( callbackUrlExpression = "http://$request.query.url", name = "subscription", operation = @Operation( method = "post", description = "payload data will be sent", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, minimum = "2", maximum = "34" )) }, responses = { @ApiResponse( responseCode = "200", description = "Return this code if the callback was received and processed successfully" ), @ApiResponse( responseCode = "205", description = "Return this code to unsubscribe from future data updates" ), @ApiResponse( responseCode = "default", description = "All other response codes will disable this callback subscription" ) })) @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", responses = { @ApiResponse( responseCode = "default", description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = CallbackTest.SubscriptionResponse.class) )) }) public SubscriptionResponse subscribe(@Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "the authentication token " + "provided after initially authenticating to the application", type = "string") @HeaderParam("x-auth-token") String token, @Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "the URL to call with response " + "data") @QueryParam("url") String url) { return null; } } static class SubscriptionResponse { public String subscriptionId; } @Test public void simpleCallbacksWithOneCallbackTest() { String openApiYAML = readIntoYaml(SimpleCallbacksTest.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " callbacks:\n" + " testCallback1:\n" + " localhost:9080/airlines/reviews/{id}/1: {}"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(expectedYAML, extractedYAML); } static class SimpleCallbacksTest { @Callbacks({ @Callback(name = "testCallback1", operation = @Operation(), callbackUrlExpression = "localhost:9080/airlines/reviews/{id}/1") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet() { } } @Test public void simpleCallbacksWithOneCallbackWithOperationTest() { String openApiYAML = readIntoYaml(SimpleCallbacksTestWithOperation.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " callbacks:\n" + " testCallback1:\n" + " http://www.url.com:\n" + " get:\n" + " summary: get all the reviews\n" + " operationId: getAllReviews\n" + " responses:\n" + " \"200\":\n" + " description: successful operation\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: integer\n" + " format: int32"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(expectedYAML, extractedYAML); } static class SimpleCallbacksTestWithOperation { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet() { } } @Test public void simpleCallbacksWithMultipleCallbackWithOperationTest() { String openApiYAML = readIntoYaml(MultipleCallbacksTestWithOperation.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " callbacks:\n" + " testCallback1:\n" + " http://www.url.com:\n" + " get:\n" + " summary: get all the reviews\n" + " operationId: getAllReviews\n" + " responses:\n" + " \"200\":\n" + " description: successful operation\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " testCallback2:\n" + " http://$request.query.url: {}"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(expectedYAML, extractedYAML); } static class MultipleCallbacksTestWithOperation { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com"), @Callback(name = "testCallback2", operation = @Operation(), callbackUrlExpression = "http://$request.query.url") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet() { } } @Test public void callbackCallbacksAnnotationTest() { String openApiYAML = readIntoYaml(CallbackCallbacksAnnotationTest.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " callbacks:\n" + " testCallback:\n" + " http://$requests.query.url: {}\n" + " testCallback1:\n" + " http://www.url.com:\n" + " get:\n" + " summary: get all the reviews\n" + " operationId: getAllReviews\n" + " responses:\n" + " \"200\":\n" + " description: successful operation\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " testCallback2:\n" + " http://$request.query.url: {}"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(expectedYAML, extractedYAML); } @Test public void repeatableCallbackCallbacksAnnotationTest() { String openApiYAML = readIntoYaml(RepeatableCallbackAnnotationTest.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " callbacks:\n" + " testCallback:\n" + " http://$requests.query.url: {}\n" + " testCallback1:\n" + " http://www.url.com:\n" + " get:\n" + " summary: get all the reviews\n" + " operationId: getAllReviews\n" + " responses:\n" + " \"200\":\n" + " description: successful operation\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " testCallback2:\n" + " http://$request.query.url: {}"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(expectedYAML, extractedYAML); } static class CallbackCallbacksAnnotationTest { @Callback(name = "testCallback", operation = @Operation(), callbackUrlExpression = "http://$requests.query.url") @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com"), @Callback(name = "testCallback2", operation = @Operation(), callbackUrlExpression = "http://$request.query.url") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet() { } } static class RepeatableCallbackAnnotationTest { @Callback(name = "testCallback", operation = @Operation(), callbackUrlExpression = "http://$requests.query.url") @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com") @Callback(name = "testCallback2", operation = @Operation(), callbackUrlExpression = "http://$request.query.url") @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet() { } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/definition/OpenApiDefinitionTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.definition; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.info.Contact; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.servers.ServerVariable; import io.swagger.v3.oas.annotations.tags.Tag; import org.testng.annotations.Test; import java.io.IOException; public class OpenApiDefinitionTest extends AbstractAnnotationTest { @Test public void testSimpleInfoGet() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "info:\n" + " title: the title\n" + " description: My API\n" + " contact:\n" + " name: Fred\n" + " url: http://gigantic-server.com\n" + " email: Fred@gigagantic-server.com\n" + " license:\n" + " name: Apache 2.0\n" + " url: http://foo.bar\n" + " version: \"0.0\"\n" + "externalDocs:\n" + " description: definition docs desc\n" + "servers:\n" + "- url: http://foo\n" + " description: server 1\n" + " variables:\n" + " var1:\n" + " description: var 1\n" + " enum:\n" + " - \"1\"\n" + " - \"2\"\n" + " default: \"1\"\n" + " var2:\n" + " description: var 2\n" + " enum:\n" + " - \"1\"\n" + " - \"2\"\n" + " default: \"1\"\n" + "security:\n" + "- req 1:\n" + " - a\n" + " - b\n" + "- req 2:\n" + " - b\n" + " - c\n" + "tags:\n" + "- name: Tag 1\n" + " description: desc 1\n" + " externalDocs:\n" + " description: docs desc\n" + "- name: Tag 2\n" + " description: desc 2\n" + " externalDocs:\n" + " description: docs desc 2\n" + "- name: Tag 3\n"; compareAsYaml(OpenApiDefinitionTest.ClassWithAnnotation.class, expectedYAML); } @OpenAPIDefinition( info = @Info( title = "the title", version = "0.0", description = "My API", license = @License(name = "Apache 2.0", url = "http://foo.bar"), contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com") ), tags = { @Tag(name = "Tag 1", description = "desc 1", externalDocs = @ExternalDocumentation(description = "docs desc")), @Tag(name = "Tag 2", description = "desc 2", externalDocs = @ExternalDocumentation(description = "docs desc 2")), @Tag(name = "Tag 3") }, externalDocs = @ExternalDocumentation(description = "definition docs desc"), security = { @SecurityRequirement(name = "req 1", scopes = {"a", "b"}), @SecurityRequirement(name = "req 2", scopes = {"b", "c"}) }, servers = { @Server( description = "server 1", url = "http://foo", variables = { @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}), @ServerVariable(name = "var2", description = "var 2", defaultValue = "1", allowableValues = {"1", "2"}) }) } ) static class ClassWithAnnotation { public void foo() { } } @Test public void testServerVariableWithoutEnum() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "info:\n" + " title: My Rest API\n" + " description: My RESTful API implementation\n" + " version: 1.0.0\n" + "servers:\n" + "- url: /{context-path}/{rest-api}\n" + " description: My REST API\n" + " variables:\n" + " context-path:\n" + " default: my-war\n" + " rest-api:\n" + " enum:\n" + " - api\n" + " - rest\n" + " - batchapi\n" + " default: api\n"; compareAsYaml(OpenApiDefinitionTest.ServerVariableWithoutEnum.class, expectedYAML); } @OpenAPIDefinition( info = @Info( title = "My Rest API", version = "1.0.0", description = "My RESTful API implementation" ), servers = { @Server( description = "My REST API", url = "/{context-path}/{rest-api}", variables = { @ServerVariable(name = "context-path", defaultValue = "my-war"), @ServerVariable(name = "rest-api", defaultValue = "api", allowableValues = {"api", "rest", "batchapi"}) } ) } ) static class ServerVariableWithoutEnum { public void foo() { } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/encoding/EncodingTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.encoding; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Encoding; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.testng.annotations.Test; import javax.ws.rs.GET; import javax.ws.rs.Path; import static org.testng.Assert.assertEquals; public class EncodingTest extends AbstractAnnotationTest { //Test encoding inside ApiResponse/Content @Test public void testSimpleGetOperationWithEncodingInApiResponse() { String openApiYAML = readIntoYaml(SimpleGetOperationWithEncodingInApiResponse.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex\n" + " operationId: simpleGet\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: string\n" + " encoding:\n" + " test:\n" + " contentType: text/plain\n" + " style: form\n" + " explode: true\n" + " allowReserved: true"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class SimpleGetOperationWithEncodingInApiResponse { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex", operationId = "simpleGet", responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema( name = "test"), encoding = @Encoding( name = "test", contentType = "text/plain", style = "FORM", allowReserved = true, explode = true))) }) @GET @Path("/path") public void simpleGet() { } } //Test encoding inside Parameter/Content @Test public void testGetOperationWithEncodingInParameter() { String openApiYAML = readIntoYaml(GetOperationWithEncodingInParameter.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex\n" + " operationId: getWithEncodingInParameter\n" + " parameters:\n" + " - name: testParam\n" + " in: query\n" + " description: A parameter for testing encoding annotation.\n" + " required: true\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: string\n" + " encoding:\n" + " testingParam:\n" + " style: form\n" + " allowReserved: true\n" + " responses:\n" + " \"200\":\n" + " description: voila!"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class GetOperationWithEncodingInParameter { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex", operationId = "getWithEncodingInParameter", parameters = { @Parameter( name = "testParam", in = ParameterIn.QUERY, description = "A parameter for testing encoding annotation.", required = true, content = @Content( mediaType = "application/json", schema = @Schema( name = "testingParam"), encoding = @Encoding( name = "testingParam", style = "FORM", allowReserved = true, explode = false)) ) }, responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet() { } } //Test encoding inside Parameter/Content @Test public void testGetOperationWithEncodingArrayInParameter() { String openApiYAML = readIntoYaml(GetOperationWithEncodingArrayInParameter.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex\n" + " operationId: getWithEncodingArrayInParameter\n" + " parameters:\n" + " - name: testParam\n" + " in: query\n" + " description: A parameter for testing encoding annotation.\n" + " required: true\n" + " content:\n" + " application/json:\n" + " schema:\n" + " title: testEncoding2\n" + " type: string\n" + " encoding:\n" + " testEncoding:\n" + " style: form\n" + " allowReserved: true\n" + " testEncoding2:\n" + " headers:\n" + " testHeader:\n" + " required: true\n" + " style: simple\n" + " style: form\n" + " allowReserved: true\n" + " responses:\n" + " \"200\":\n" + " description: voila!"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class GetOperationWithEncodingArrayInParameter { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex", operationId = "getWithEncodingArrayInParameter", parameters = { @Parameter( name = "testParam", in = ParameterIn.QUERY, description = "A parameter for testing encoding annotation.", required = true, content = @Content( mediaType = "application/json", schema = @Schema( name = "testEncoding", title = "testEncoding2"), encoding = { @Encoding( name = "testEncoding", style = "FORM", allowReserved = true, explode = false), @Encoding( name = "testEncoding2", style = "FORM", allowReserved = true, explode = false, headers = @Header( name = "testHeader", required = true))}) ) }, responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet() { } } //Test encoding inside RequestBody/Content @Test public void testGetOperationWithEncodingInRequestBody() { String openApiYAML = readIntoYaml(GetOperationWithEncodingInRequestBody.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with encoding in requestBody\n" + " operationId: getWithEncodingInRequestBody\n" + " requestBody:\n" + " description: Test requestBody with encoding.\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: string\n" + " encoding:\n" + " testRequestBody:\n" + " contentType: text/plain\n" + " style: form\n" + " explode: true\n" + " required: true\n" + " responses:\n" + " \"200\":\n" + " description: voila!"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class GetOperationWithEncodingInRequestBody { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with encoding in requestBody", operationId = "getWithEncodingInRequestBody", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet(@RequestBody( description = "Test requestBody with encoding.", required = true, content = @Content( mediaType = "application/json", schema = @Schema( name = "testRequestBody"), encoding = @Encoding( name = "testRequestBody", contentType = "text/plain", style = "FORM", explode = true))) String testRequestBody) { } } //Test an operation with ApiResponse but no Content/Encoding in it @Test public void testSimpleGetOperation() { String openApiYAML = readIntoYaml(SimpleGetOperationTest.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class SimpleGetOperationTest { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/path") public void simpleGet() { } } //Test an operation with no response, parameters, or requestBody @Test public void testSimpleGetOperationWithoutResponses() { String openApiYAML = readIntoYaml(SimpleGetWithoutResponses.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs or responses\n" + " operationId: getWithNoParametersAndNoResponses\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class SimpleGetWithoutResponses { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs or responses", operationId = "getWithNoParametersAndNoResponses") @GET @Path("/path") public void simpleGet() { } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/examples/ExamplesTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.examples; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.testng.annotations.Test; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import static org.testng.Assert.assertEquals; public class ExamplesTest extends AbstractAnnotationTest { @Test public void testRequestBodyContentExample() { compareToYamlFile(ExamplesTest.RequestBodyContentExample.class, "examples/"); compareToYamlFile(ExamplesTest.RequestBodyContentExampleWithConsumes.class, "examples/"); compareToYamlFile(ExamplesTest.RequestBodyContentExampleWithMediatype.class, "examples/"); compareToYamlFile(ExamplesTest.RequestBodyContentExampleWithMediatype.class, "examples/"); compareToYamlFile(ExamplesTest.RequestBodyContentExampleWithSchema.class, "examples/"); compareToYamlFile(ExamplesTest.RequestBodyContentExampleWithSchemaImplementation.class, "examples/"); } @Test public void testResponseExample() { compareToYamlFile(ExamplesTest.ResponseExample.class, "examples/"); compareToYamlFile(ExamplesTest.ResponseExampleSchema.class, "examples/"); compareToYamlFile(ExamplesTest.ResponseExampleSchemaImplementation.class, "examples/"); } @Test public void testParameterExample() { compareToYamlFile(ExamplesTest.ParameterExample.class, "examples/"); } @Test public void testAnnotatedModel() { compareToYamlFile(ExamplesTest.AnnotatedModelExample.class, "examples/"); compareToYamlFile(ExamplesTest.AnnotatedModelAndContentExample.class, "examples/"); } static class ResponseExampleSchema { @Path("/test") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example" ), examples = { @ExampleObject( name = "Default Response", value = "SubscriptionResponse", summary = "Subscription Response Example" ) } )) }) public ExamplesTest.SubscriptionResponse subscribe() { return null; } } static class ResponseExampleSchemaImplementation { @Path("/test") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = Subscription.class ), examples = { @ExampleObject( name = "Default Response", value = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}", summary = "Subscription Response Example" ) } )) }) public ExamplesTest.SubscriptionResponse subscribe() { return null; } } static class ResponseExample { @Path("/test") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", examples = { @ExampleObject( name = "Default Response", value = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}", summary = "Subscription Response Example" ) } )) }) public ExamplesTest.SubscriptionResponse subscribe() { return null; } } static class ParameterExample{ @Path("/test") @POST public ExamplesTest.Subscription testRequestBody( @Parameter( in = ParameterIn.QUERY, description = "subscription param", required = true, example = "1", schema = @Schema( type = "string", description = "the Sub", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example" ), content = @Content( mediaType = "application/json", examples = { @ExampleObject( name = "Default Request", description = "Subscription Example Description", value = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}", summary = "Subscription Example") } ), examples = { @ExampleObject( name = "ex 1", value = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}" ), @ExampleObject( name = "ex 2", value = "{\"subscriptionId\" : \"12\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"22\"}}" ) } ) String subId) { return null; } } static class RequestBodyContentExample{ @Path("/test") @POST public ExamplesTest.Subscription testRequestBody( @RequestBody( description = "Created user object", required = true, content = @Content( examples = { @ExampleObject( name = "Default Request", value = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}", summary = "Subscription Example") } ) ) ExamplesTest.Subscription sub) { return null; } } static class RequestBodyContentExampleWithSchemaImplementation{ @Path("/test") @POST public ExamplesTest.Subscription testRequestBody( @RequestBody( description = "Created user object", required = true, content = @Content( schema = @Schema( implementation = ExamplesTest.Subscription.class ), examples = { @ExampleObject( name = "Default Request", value = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}", summary = "Subscription Example") } ) ) ExamplesTest.Subscription sub) { return null; } } static class RequestBodyContentExampleWithSchema{ @Path("/test") @POST public ExamplesTest.Subscription testRequestBody( @RequestBody( description = "Created user object", required = true, content = @Content( schema = @Schema( type = "string", description = "the Sub", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example" ), examples = { @ExampleObject( name = "Default Request", value = "3", summary = "Subscription Example") } ) ) ExamplesTest.Subscription sub) { return null; } } static class RequestBodyContentExampleWithMediatype{ @Path("/test") @POST public ExamplesTest.Subscription testRequestBody( @RequestBody( description = "Created user object", required = true, content = @Content( mediaType = "application/json", examples = { @ExampleObject( name = "Default Request", value = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}", summary = "Subscription Example") } ) ) ExamplesTest.Subscription sub) { return null; } } static class RequestBodyContentExampleWithConsumes{ @Path("/test") @POST @Consumes("application/json") public ExamplesTest.Subscription testRequestBody( @RequestBody( description = "Created user object", required = true, content = @Content( examples = { @ExampleObject( name = "Default Request", value = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}", summary = "Subscription Example") } ) ) ExamplesTest.Subscription sub) { return null; } } static class AnnotatedModelExample{ @Path("/test") @POST public ExamplesTest.AnnotatedSubscription testAnnotatedModel( @RequestBody( description = "Created user object", required = true ) ExamplesTest.AnnotatedSubscription sub) { return null; } } static class AnnotatedModelAndContentExample{ @Path("/test") @POST public ExamplesTest.AnnotatedSubscription testAnnotatedModel( @RequestBody( description = "Created user object", required = true, content = @Content( mediaType = "application/json", examples = { @ExampleObject( name = "Default Request", value = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}", summary = "Subscription Example"), @ExampleObject( name = "Default Request 2", value = "{\"subscriptionId\" : \"12\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"22\"}}", summary = "Subscription Example 2") } ) ) ExamplesTest.AnnotatedSubscription sub) { return null; } } @Test public void testFullExample() { String openApiYAML = readIntoYaml(ExamplesTest.SimpleOperations.class); int start = openApiYAML.indexOf("/test:"); int end = openApiYAML.length() - 1; String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "/test:\n" + " post:\n" + " description: \"subscribes a client to updates relevant to the requestor's account,\\\n" + " \\ as identified by the input token. The supplied url will be used as the\\\n" + " \\ delivery address for response payloads\"\n" + " operationId: subscribe\n" + " parameters:\n" + " - name: subscriptionId\n" + " in: path\n" + " required: true\n" + " style: simple\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " examples:\n" + " subscriptionId_1:\n" + " summary: Subscription number 12345\n" + " description: subscriptionId_1\n" + " value: 12345\n" + " externalValue: Subscription external value 1\n" + " subscriptionId_2:\n" + " summary: Subscription number 54321\n" + " description: subscriptionId_2\n" + " value: 54321\n" + " externalValue: Subscription external value 2\n" + " example: example\n" + " requestBody:\n" + " description: Created user object\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string\n" + " description: the generated UUID\n" + " format: uuid\n" + " readOnly: true\n" + " example: Schema example\n" + " examples:\n" + " Default Response:\n" + " summary: Subscription Response Example\n" + " description: Default Response\n" + " value: SubscriptionResponse\n" + " externalValue: Subscription Response value 1\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string\n" + " description: the generated UUID\n" + " format: uuid\n" + " readOnly: true\n" + " example: Schema example\n" + " examples:\n" + " Default Response:\n" + " summary: Subscription Response Example\n" + " description: Default Response\n" + " value: SubscriptionResponse\n" + " externalValue: Subscription Response value 1\n" + "components:\n" + " schemas:\n" + " SubscriptionResponse:\n" + " type: object\n" + " properties:\n" + " subscriptionId:\n" + " type: string\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " username:\n" + " type: string\n" + " firstName:\n" + " type: string\n" + " lastName:\n" + " type: string\n" + " email:\n" + " type: string\n" + " password:\n" + " type: string\n" + " phone:\n" + " type: string\n" + " userStatus:\n" + " type: integer\n" + " description: User Status\n" + " format: int32\n" + " xml:\n" + " name: User"; assertEquals(extractedYAML, expectedYAML); } static class SimpleOperations { @Path("/test") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(implementation = ExamplesTest.SubscriptionResponse.class), style = ParameterStyle.SIMPLE, example = "example", examples = { @ExampleObject(name = "subscriptionId_1", value = "12345", summary = "Subscription number 12345", externalValue = "Subscription external value 1"), @ExampleObject(name = "subscriptionId_2", value = "54321", summary = "Subscription number 54321", externalValue = "Subscription external value 2") }) }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example" ), examples = { @ExampleObject(name = "Default Response", value = "SubscriptionResponse", summary = "Subscription Response Example", externalValue = "Subscription Response value 1") } )) }) public ExamplesTest.SubscriptionResponse subscribe(@RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example"), examples = { @ExampleObject(name = "Default Response", value = "SubscriptionResponse", summary = "Subscription Response Example", externalValue = "Subscription Response value 1") })) User user) { return null; } } static class SubscriptionResponse { public String subscriptionId; } static class Subscription { public String subscriptionId; public SubscriptionItem subscriptionItem; } static class SubscriptionItem { public String subscriptionItemId; } @Schema(example = "{\"subscriptionId\" : \"1\", \"subscriptionItem\" : {\"subscriptionItemId\" : \"2\"}}") static class AnnotatedSubscription { public String subscriptionId; public AnnotatedSubscriptionItem subscriptionItem; } @Schema(example = "{\"subscriptionItemId\" : \"1\"}") static class AnnotatedSubscriptionItem { public String subscriptionItemId; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/info/InfoTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.info; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.info.Contact; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.info.License; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; public class InfoTest extends AbstractAnnotationTest { @Test public void testSimpleInfoGet() { String openApiYAML = readIntoYaml(InfoTest.ClassWithInfoAnnotation.class); int start = openApiYAML.indexOf("info:"); int end = openApiYAML.length() - 1; String expectedYAML = "info:\n" + " title: the title\n" + " description: My API\n" + " contact:\n" + " name: Fred\n" + " url: http://gigantic-server.com\n" + " email: Fred@gigagantic-server.com\n" + " license:\n" + " name: Apache 2.0\n" + " url: http://foo.bar\n" + " version: \"0.0\""; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } @OpenAPIDefinition(info = @Info( title = "the title", version = "0.0", description = "My API", license = @License(name = "Apache 2.0", url = "http://foo.bar"), contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com")) ) static class ClassWithInfoAnnotation { // do something here } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/AnnotatedOperationMethodTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.operations; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.jaxrs2.resources.GenericResponsesResource; import io.swagger.v3.jaxrs2.resources.HiddenAnnotatedUserResource; import io.swagger.v3.jaxrs2.resources.HiddenUserResource; import io.swagger.v3.jaxrs2.resources.PetResource; import io.swagger.v3.jaxrs2.resources.PetResourceSlashesinPath; import io.swagger.v3.jaxrs2.resources.SimpleUserResource; import io.swagger.v3.jaxrs2.resources.UserResource; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import org.testng.annotations.Test; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.io.IOException; import static org.testng.Assert.assertEquals; public class AnnotatedOperationMethodTest extends AbstractAnnotationTest { @Test public void testSimpleGetOperation() { String openApiYAML = readIntoYaml(SimpleGetOperationTest.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " deprecated: true"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class SimpleGetOperationTest { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex", operationId = "getWithNoParameters", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!") } ) @GET @Path("/path") public void simpleGet() { } } @Test public void testSimpleGetOperationWithoutResponses() { String openApiYAML = readIntoYaml(SimpleGetWithoutResponses.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs or responses\n" + " operationId: getWithNoParametersAndNoResponses\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " deprecated: true"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class SimpleGetWithoutResponses { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs or responses", operationId = "getWithNoParametersAndNoResponses", deprecated = true ) @GET @Path("/path") public void simpleGet() { } } @Test public void testGetOperationWithResponsePayloadAndAlternateCodes() { String openApiYAML = readIntoYaml(GetOperationWithResponsePayloadAndAlternateCodes.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.indexOf("components:"); String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleResponseSchema\"\n" + " default:\n" + " description: boo\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/GenericError\"\n" + " examples:\n" + " boo:\n" + " summary: example of boo\n" + " description: boo\n" + " value: example\n" + " externalValue: example of external value\n" + " deprecated: true\n"; assertEquals(extractedYAML, expectedYAML); } static class GetOperationWithResponsePayloadAndAlternateCodes { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema(implementation = SampleResponseSchema.class) ) ), @ApiResponse( description = "boo", content = @Content( mediaType = "*/*", schema = @Schema(implementation = GenericError.class), examples = { @ExampleObject(name = "boo", value = "example", summary = "example of boo", externalValue = "example of external value") } ) ) } ) @Path("/path") @GET public void simpleGet() { } } static class SampleResponseSchema { @Schema(description = "the user id") public String id; } static class SampleHeaderSchema { public String id; } static class GenericError { public int code; public String message; } @Test(description = "reads an operation with response examples defined") public void testOperationWithResponseExamples() { String openApiYAML = readIntoYaml(GetOperationWithResponseExamples.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.indexOf("components:"); String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleResponseSchema\"\n" + " examples:\n" + " basic:\n" + " summary: shows a basic example\n" + " description: basic\n" + " value: \"{id: 19877734}\"\n" + " deprecated: true\n"; assertEquals(extractedYAML, expectedYAML); } @Test(description = "reads an operation with response examples defined") public void testOperationWithParameterExample() { String openApiYAML = readIntoYaml(GetOperationWithParameterExample.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.indexOf("components:"); String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with a parameter example\n" + " operationId: getWithPayloadResponse\n" + " parameters:\n" + " - in: query\n" + " schema:\n" + " type: string\n" + " example:\n" + " id: 19877734\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleResponseSchema\"\n" + " examples:\n" + " basic:\n" + " summary: shows a basic example\n" + " description: basic\n" + " value: \"{id: 19877734}\"\n" + " deprecated: true\n"; assertEquals(extractedYAML, expectedYAML); } static class GetOperationWithResponseExamples { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema(implementation = SampleResponseSchema.class), examples = { @ExampleObject( name = "basic", summary = "shows a basic example", value = "{id: 19877734}") } ) ) } ) @GET @Path("/path") public void simpleGet() { } } static class GetOperationWithParameterExample { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with a parameter example", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema(implementation = SampleResponseSchema.class), examples = { @ExampleObject( name = "basic", summary = "shows a basic example", value = "{id: 19877734}") } ) ) } ) @GET @Path("/path") public void simpleGet(@Parameter(in = ParameterIn.QUERY, example = "{\"id\": 19877734}") String exParam) { } } static class GetOperationWithResponseSingleHeader { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", headers = {@Header( name = "Rate-Limit-Limit", description = "The number of allowed requests in the current period", schema = @Schema(type = "integer"))}) }) @GET @Path("/path") public void simpleGet() { } } @Test public void testOperationWithResponseSingleHeader() { String openApiYAML = readIntoYaml(GetOperationWithResponseSingleHeader.class); int start = openApiYAML.indexOf("get:"); String extractedYAML = openApiYAML.substring(start); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " headers:\n" + " Rate-Limit-Limit:\n" + " description: The number of allowed requests in the current period\n" + " style: simple\n" + " schema:\n" + " type: integer\n" + " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } static class GetOperationWithResponseMultipleHeaders { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", headers = {@Header( explode = Explode.TRUE, name = "Rate-Limit-Limit", description = "The number of allowed requests in the current period", schema = @Schema(type = "integer")), @Header( name = "X-Rate-Limit-Desc", description = "The description of rate limit", schema = @Schema(type = "string"))}) }) @GET @Path("/path") public void simpleGet() { } } @Test public void testOperationWithResponseArraySchema() { String openApiYAML = readIntoYaml(GetOperationResponseHeaderWithArraySchema.class); int start = openApiYAML.indexOf("get:"); String extractedYAML = openApiYAML.substring(start); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " headers:\n" + " Rate-Limit-Limit:\n" + " description: The number of allowed requests in the current period\n" + " style: simple\n" + " schema:\n" + " maxItems: 10\n" + " minItems: 1\n" + " type: array\n" + " items:\n" + " type: integer\n" + " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } static class GetOperationResponseHeaderWithArraySchema { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", headers = {@Header( name = "Rate-Limit-Limit", description = "The number of allowed requests in the current period", array = @ArraySchema(maxItems = 10, minItems = 1,schema = @Schema(type = "integer")))})}) @GET @Path("/path") public void simpleGet() { } } static class GetOperationResponseWithoutHiddenHeader { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", headers = {@Header( hidden = true, name = "Rate-Limit-Limit", description = "The number of allowed requests in the current period", schema = @Schema(type = "integer")), @Header( name = "X-Rate-Limit-Desc", description = "The description of rate limit", schema = @Schema(type = "string"))}) }) @GET @Path("/path") public void simpleGet() { } } static class GetOperationWithResponseMultipleHeadersAndExamples { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", headers = {@Header( examples = { @ExampleObject( name = "ex 1", description = "example description", value = "example value" ), @ExampleObject( name = "ex 2", description = "example description 2", value = "example value 2" ) }, name = "Rate-Limit-Limit", description = "The number of allowed requests in the current period", schema = @Schema(type = "object")), @Header( name = "X-Rate-Limit-Desc", description = "The description of rate limit", array = @ArraySchema(schema = @Schema()), example = "example1")}) }) @GET @Path("/path") public void simpleGet() { } } static class GetOperationResponseWithHeaderExplodeAttribute { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", headers = {@Header( name = "Rate-Limit-Limit", description = "The number of allowed requests in the current period", explode = Explode.TRUE, schema = @Schema(type = "object")), @Header( name = "X-Rate-Limit-Desc", description = "The description of rate limit", explode = Explode.FALSE, schema = @Schema(type = "array"))}) }) @GET @Path("/path") public void simpleGet() { } } @Test public void testOperationWithResponseMultipleHeaders() { String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeaders.class); int start = openApiYAML.indexOf("get:"); String extractedYAML = openApiYAML.substring(start); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " headers:\n" + " X-Rate-Limit-Desc:\n" + " description: The description of rate limit\n" + " style: simple\n" + " schema:\n" + " type: string\n" + " Rate-Limit-Limit:\n" + " description: The number of allowed requests in the current period\n" + " style: simple\n" + " schema:\n" + " type: integer\n" + " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } static class GetOperationWithResponseMultipleHeadersWithImplementationSchema { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", headers = {@Header( explode = Explode.TRUE, name = "Rate-Limit-Limit", description = "The number of allowed requests in the current period", array = @ArraySchema(maxItems = 10, minItems = 1,schema = @Schema(implementation = SampleHeaderSchema.class))), @Header( explode = Explode.TRUE, name = "X-Rate-Limit-Desc", description = "The description of rate limit", schema = @Schema(implementation = SampleHeaderSchema.class))})}) @GET @Path("/path") public void simpleGet() { } } @Test public void testOperationWithResponseMultipleHeadersImplementationSchema() { String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeadersWithImplementationSchema.class); int start = openApiYAML.indexOf("get:"); String extractedYAML = openApiYAML.substring(start); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " headers:\n" + " X-Rate-Limit-Desc:\n" + " description: The description of rate limit\n" + " style: simple\n" + " explode: true\n" + " schema:\n" + " $ref: \"#/components/schemas/SampleHeaderSchema\"\n" + " Rate-Limit-Limit:\n" + " description: The number of allowed requests in the current period\n" + " style: simple\n" + " explode: true\n" + " schema:\n" + " maxItems: 10\n" + " minItems: 1\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/SampleHeaderSchema\"\n" + " deprecated: true\n" + "components:\n" + " schemas:\n" + " SampleHeaderSchema:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n"; assertEquals(expectedYAML, extractedYAML); } @Test public void testOperationWithResponseMultipleHeadersAndExplodeAttribute() { String openApiYAML = readIntoYaml(GetOperationResponseWithHeaderExplodeAttribute.class); int start = openApiYAML.indexOf("get:"); String extractedYAML = openApiYAML.substring(start); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " headers:\n" + " X-Rate-Limit-Desc:\n" + " description: The description of rate limit\n" + " style: simple\n" + " explode: false\n" + " schema:\n" + " type: array\n" + " Rate-Limit-Limit:\n" + " description: The number of allowed requests in the current period\n" + " style: simple\n" + " explode: true\n" + " schema:\n" + " type: object\n" + " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } @Test public void testOperationResponseWithoutHiddenHeader() { String openApiYAML = readIntoYaml(GetOperationResponseWithoutHiddenHeader.class); int start = openApiYAML.indexOf("get:"); String extractedYAML = openApiYAML.substring(start); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " headers:\n" + " X-Rate-Limit-Desc:\n" + " description: The description of rate limit\n" + " style: simple\n" + " schema:\n" + " type: string\n" + " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } @Test public void testOperationWithResponseMultipleHeadersAndExamples() { String openApiYAML = readIntoYaml(GetOperationWithResponseMultipleHeadersAndExamples.class); int start = openApiYAML.indexOf("get:"); String extractedYAML = openApiYAML.substring(start); String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex output\n" + " operationId: getWithPayloadResponse\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " headers:\n" + " X-Rate-Limit-Desc:\n" + " description: The description of rate limit\n" + " style: simple\n" + " example: example1\n" + " Rate-Limit-Limit:\n" + " description: The number of allowed requests in the current period\n" + " style: simple\n" + " schema:\n" + " type: object\n" + " examples:\n" + " ex 1:\n" + " description: example description\n" + " value: example value\n" + " ex 2:\n" + " description: example description 2\n" + " value: example value 2\n" + " deprecated: true\n"; assertEquals(expectedYAML, extractedYAML); } @Test(description = "reads the pet resource from sample") public void testCompletePetResource() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /pet/findByTags:\n" + " get:\n" + " summary: Finds Pets by tags\n" + " description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.\n" + " operationId: findPetsByTags\n" + " parameters:\n" + " - name: tags\n" + " in: query\n" + " description: Tags to filter by\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: Pets matching criteria\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " \"400\":\n" + " description: Invalid tag value\n" + " deprecated: true\n" + " /pet/findByCategory/{category}:\n" + " get:\n" + " summary: Finds Pets by category\n" + " operationId: findPetsByCategory\n" + " parameters:\n" + " - name: category\n" + " in: path\n" + " description: Category value that need to be considered for filter\n" + " required: true\n" + " style: matrix\n" + " schema:\n" + " $ref: \"#/components/schemas/Category\"\n" + " - name: skip\n" + " in: query\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " - name: limit\n" + " in: query\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " default:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " \"400\":\n" + " description: Invalid category value\n" + " /pet/{petId}:\n" + " get:\n" + " summary: Find pet by ID\n" + " description: Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions\n" + " operationId: getPetById\n" + " parameters:\n" + " - name: petId\n" + " in: path\n" + " description: ID of pet that needs to be fetched\n" + " required: true\n" + " schema:\n" + " type: integer\n" + " format: int64\n" + " responses:\n" + " default:\n" + " description: The pet\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " \"400\":\n" + " description: Invalid ID supplied\n" + " \"404\":\n" + " description: Pet not found\n" + " /pet/bodynoannotation:\n" + " post:\n" + " summary: Add a new pet to the store no annotation\n" + " operationId: addPetNoAnnotation\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " responses:\n" + " \"405\":\n" + " description: Invalid input\n" + " /pet/bodyid:\n" + " post:\n" + " summary: Add a new pet to the store passing an integer with generic parameter annotation\n" + " operationId: addPetByInteger\n" + " requestBody:\n" + " description: Pet object that needs to be added to the store\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " application/xml:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " required: true\n" + " responses:\n" + " \"405\":\n" + " description: Invalid input\n" + " /pet/bodyidnoannotation:\n" + " post:\n" + " summary: Add a new pet to the store passing an integer without parameter annotation\n" + " operationId: addPetByIntegerNoAnnotation\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " application/xml:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " \"405\":\n" + " description: Invalid input\n" + " /pet:\n" + " put:\n" + " summary: Update an existing pet\n" + " operationId: updatePet\n" + " requestBody:\n" + " description: Pet object that needs to be added to the store\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " required: true\n" + " responses:\n" + " \"400\":\n" + " description: Invalid ID supplied\n" + " \"404\":\n" + " description: Pet not found\n" + " \"405\":\n" + " description: Validation exception\n" + " post:\n" + " summary: Add a new pet to the store\n" + " operationId: addPet\n" + " requestBody:\n" + " description: Pet object that needs to be added to the store\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " required: true\n" + " responses:\n" + " \"405\":\n" + " description: Invalid input\n" + " /pet/findByStatus:\n" + " get:\n" + " summary: Finds Pets by status\n" + " description: Multiple status values can be provided with comma separated strings\n" + " operationId: findPetsByStatus\n" + " parameters:\n" + " - name: status\n" + " in: query\n" + " description: Status values that need to be considered for filter\n" + " required: true\n" + " schema:\n" + " type: string\n" + " - name: skip\n" + " in: query\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " - name: limit\n" + " in: query\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " default:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " \"400\":\n" + " description: Invalid status value\n" + "components:\n" + " schemas:\n" + " Category:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Category\n" + " Tag:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Tag\n" + " Pet:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " category:\n" + " $ref: \"#/components/schemas/Category\"\n" + " name:\n" + " type: string\n" + " photoUrls:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " type: string\n" + " xml:\n" + " name: photoUrl\n" + " tags:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " $ref: \"#/components/schemas/Tag\"\n" + " status:\n" + " type: string\n" + " description: pet status in the store\n" + " enum:\n" + " - available,pending,sold\n" + " xml:\n" + " name: Pet"; compareAsYaml(PetResource.class, expectedYAML); compareAsYaml(PetResourceSlashesinPath.class, expectedYAML); } @Test(description = "reads the resource with generic response from sample") public void testGenericResponseResource() throws IOException { String yaml = "openapi: 3.0.1\n" + "paths:\n" + " /:\n" + " get:\n" + " summary: Returns a list of somethings\n" + " operationId: getSomethings\n" + " responses:\n" + " default:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SomethingResponse\"\n" + " /overridden:\n" + " get:\n" + " summary: Returns a list of somethings\n" + " operationId: getSomethingsOverridden\n" + " responses:\n" + " default:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Something\"\n" + "components:\n" + " schemas:\n" + " SomethingResponse:\n" + " type: object\n" + " properties:\n" + " data:\n" + " $ref: \"#/components/schemas/DataSomething\"\n" + " DataSomething:\n" + " type: object\n" + " properties:\n" + " items:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Something\"\n" + " Something:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n"; compareAsYaml(GenericResponsesResource.class, yaml); } @Test(description = "reads the user resource from sample") public void testCompleteUserResource() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /user:\n" + " post:\n" + " summary: Create user\n" + " description: This can only be done by the logged in user.\n" + " operationId: createUser\n" + " requestBody:\n" + " description: Created user object\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " 'application/json': {}\n" + " 'application/xml': {}\n" + " /user/createWithArray:\n" + " post:\n" + " summary: Creates list of users with given input array\n" + " operationId: createUsersWithArrayInput\n" + " requestBody:\n" + " description: List of user object\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/User\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " 'application/json': {}\n" + " 'application/xml': {}\n" + " /user/createWithList:\n" + " post:\n" + " summary: Creates list of users with given input array\n" + " operationId: createUsersWithListInput\n" + " requestBody:\n" + " description: List of user object\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/User\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " 'application/json': {}\n" + " 'application/xml': {}\n" + " /user/{username}:\n" + " get:\n" + " summary: Get user by user name\n" + " operationId: getUserByName\n" + " parameters:\n" + " - name: username\n" + " in: path\n" + " description: 'The name that needs to be fetched. Use user1 for testing. '\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: The user\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " \"400\":\n" + " description: User not found\n" + " put:\n" + " summary: Updated user\n" + " description: This can only be done by the logged in user.\n" + " operationId: updateUser\n" + " parameters:\n" + " - name: username\n" + " in: path\n" + " description: name that need to be deleted\n" + " required: true\n" + " schema:\n" + " type: string\n" + " examples:\n" + " example2:\n" + " summary: Summary example 2\n" + " description: example2\n" + " value: example2\n" + " externalValue: external value 2\n" + " example1:\n" + " summary: Summary example 1\n" + " description: example1\n" + " value: example1\n" + " externalValue: external value 1\n" + " requestBody:\n" + " description: Updated user object\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " required: true\n" + " responses:\n" + " \"200\":\n" + " description: user updated\n" + " \"400\":\n" + " description: Invalid user supplied\n" + " \"404\":\n" + " description: User not found\n" + " delete:\n" + " summary: Delete user\n" + " description: This can only be done by the logged in user.\n" + " operationId: deleteUser\n" + " parameters:\n" + " - name: username\n" + " in: path\n" + " description: The name that needs to be deleted\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " \"200\":\n" + " description: user deteled\n" + " \"400\":\n" + " description: Invalid username supplied\n" + " \"404\":\n" + " description: User not found\n" + " /user/login:\n" + " get:\n" + " summary: Logs user into the system\n" + " operationId: loginUser\n" + " parameters:\n" + " - name: username\n" + " in: query\n" + " description: The user name for login\n" + " required: true\n" + " schema:\n" + " type: string\n" + " - name: password\n" + " in: query\n" + " description: The password for login in clear text\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: Successfully logged in\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: string\n" + " application/xml:\n" + " schema:\n" + " type: string\n" + " \"400\":\n" + " description: Invalid username/password supplied\n" + " /user/logout:\n" + " get:\n" + " summary: Logs out current logged in user session\n" + " operationId: logoutUser\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " 'application/json': {}\n" + " 'application/xml': {}\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " username:\n" + " type: string\n" + " firstName:\n" + " type: string\n" + " lastName:\n" + " type: string\n" + " email:\n" + " type: string\n" + " password:\n" + " type: string\n" + " phone:\n" + " type: string\n" + " userStatus:\n" + " type: integer\n" + " description: User Status\n" + " format: int32\n" + " xml:\n" + " name: User"; compareAsYaml(UserResource.class, expectedYAML); } @Test(description = "reads the simple user resource from sample") public void testSimpleUserResource() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /user:\n" + " post:\n" + " summary: Create user\n" + " description: This can only be done by the logged in user.\n" + " operationId: createUser\n" + " requestBody:\n" + " description: Created user object\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " 'application/json': {}\n" + " 'application/xml': {}\n" + " /user/createUserWithReturnType:\n" + " post:\n" + " summary: Create user with return type\n" + " description: This can only be done by the logged in user.\n" + " operationId: createUserWithReturnType\n" + " requestBody:\n" + " description: Created user object\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " /user/createUserWithResponseAnnotation:\n" + " post:\n" + " summary: Create user with response annotation\n" + " description: This can only be done by the logged in user.\n" + " operationId: createUserWithResponseAnnotation\n" + " requestBody:\n" + " description: Created user object\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " required: true\n" + " responses:\n" + " \"200\":\n" + " description: aaa\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " /user/createUserWithReturnTypeAndResponseAnnotation:\n" + " post:\n" + " summary: Create user with return type and response annotation\n" + " description: This can only be done by the logged in user.\n" + " operationId: createUserWithReturnTypeAndResponseAnnotation\n" + " requestBody:\n" + " description: Created user object\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " required: true\n" + " responses:\n" + " \"200\":\n" + " description: aaa\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " username:\n" + " type: string\n" + " firstName:\n" + " type: string\n" + " lastName:\n" + " type: string\n" + " email:\n" + " type: string\n" + " password:\n" + " type: string\n" + " phone:\n" + " type: string\n" + " userStatus:\n" + " type: integer\n" + " description: User Status\n" + " format: int32\n" + " xml:\n" + " name: User"; compareAsYaml(SimpleUserResource.class, expectedYAML); } @Test(description = "reads and skips the hidden user resource") public void testHiddenUserResource() { String openApiYAML = readIntoYaml(HiddenUserResource.class); assertEquals(openApiYAML, "openapi: 3.0.1\n"); } @Test(description = "reads and skips the hidden user resource") public void testHiddenAnnotatedUserResource() throws IOException { String openApiYAML = readIntoYaml(HiddenAnnotatedUserResource.class); assertEquals(openApiYAML, "openapi: 3.0.1\n"); compareAsYaml(HiddenAnnotatedUserResource.HiddenAnnotatedUserResourceMethodAndData.class, "openapi: 3.0.1\n" + "paths:\n" + " /user/2:\n" + " post:\n" + " summary: Create user\n" + " description: This can only be done by the logged in user.\n" + " operationId: createUserWithHiddenBeanProperty\n" + " requestBody:\n" + " description: Created user object\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/UserResourceBean\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " 'application/json': {}\n" + " 'application/xml': {}\n" + "components:\n" + " schemas:\n" + " UserResourceBean:\n" + " type: object\n" + " properties:\n" + " foo:\n" + " type: string"); } @Test public void testSimpleGetOperationWithSecurity() { String openApiYAML = readIntoYaml(SimpleGetOperationWithSecurity.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " security:\n" + " - petstore-auth:\n" + " - write:pets"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(expectedYAML, extractedYAML); } static class SimpleGetOperationWithSecurity { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }, security = @SecurityRequirement( name = "petstore-auth", scopes = "write:pets")) @GET @Path("/path") public void simpleGet() { } } @Test public void testSimpleGetOperationWithMultipleSecurity() { String openApiYAML = readIntoYaml(SimpleGetOperationWithMultipleSecurityScopes.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " security:\n" + " - petstore-auth:\n" + " - write:pets\n" + " - read:pets"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class SimpleGetOperationWithMultipleSecurityScopes { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }, security = @SecurityRequirement( name = "petstore-auth", scopes = {"write:pets", "read:pets"})) @GET @Path("/path") public void simpleGet() { } } @Test public void testSimpleGetOperationWithMultipleSecurityAnnotations() { String openApiYAML = readIntoYaml(SimpleGetOperationWithMultipleSecurityAnnotations.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation\n" + " description: Defines a simple get operation with no inputs and a complex\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " security:\n" + " - review-auth:\n" + " - write:review\n" + " - petstore-auth:\n" + " - write:pets\n" + " - read:pets\n" + " - api_key: []"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class SimpleGetOperationWithMultipleSecurityAnnotations { @SecurityRequirement(name = "review-auth", scopes = {"write:review"}) @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }, security = {@SecurityRequirement( name = "petstore-auth", scopes = {"write:pets", "read:pets"}), @SecurityRequirement( name = "api_key", scopes = {}),}) @GET @Path("/path") public void simpleGet() { } } @Test public void testSimpleDeprecatedGetOperation() { String openApiYAML = readIntoYaml(SimpleDeprecatedGetOperationTest.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Deprecated get operation\n" + " description: Defines a deprecated get operation with no inputs and a complex\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " deprecated: true"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } static class SimpleDeprecatedGetOperationTest { @Operation( summary = "Deprecated get operation", description = "Defines a deprecated get operation with no inputs and a complex", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") } ) @GET @Path("/path") @Deprecated public void deprecatedGet() { } } @Test public void testSimpleGetOperationInDeprecatedClass() { String openApiYAML = readIntoYaml(DeprecatedSimpleGetOperationTest.class); int start = openApiYAML.indexOf("get:"); int end = openApiYAML.length() - 1; String expectedYAML = "get:\n" + " summary: Simple get operation in deprecated class\n" + " description: Defines a simple get operation in a deprecated class with no inputs\n" + " operationId: getWithNoParameters\n" + " responses:\n" + " \"200\":\n" + " description: voila!\n" + " deprecated: true"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYAML); } @Deprecated static class DeprecatedSimpleGetOperationTest { @Operation( summary = "Simple get operation in deprecated class", description = "Defines a simple get operation in a deprecated class with no inputs", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") } ) @GET @Path("/path") public void simpleGet() { } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/operations/MergedOperationTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.operations; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.testng.annotations.Test; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import static org.testng.Assert.assertEquals; public class MergedOperationTest extends AbstractAnnotationTest { @Test(description = "shows a response when no annotation is present") public void testUnannotatedMethod() { String yaml = readIntoYaml(UnannotatedMethodClass.class); String expectedYaml = "openapi: 3.0.1\n"; assertEquals(yaml, expectedYaml); } static class UnannotatedMethodClass { @GET public SimpleResponse getSimpleResponse() { return null; } } static class SimpleResponse { private String id; } @Test(description = "shows how a method with parameters and no special annotations is processed") public void testAnnotatedParameters() { String yaml = readIntoYaml(MethodWithParameters.class); assertEquals(yaml, "openapi: 3.0.1\n" + "paths:\n" + " /findAll:\n" + " get:\n" + " description: method with parameters\n" + " operationId: getSimpleResponseWithParameters\n" + " parameters:\n" + " - name: id\n" + " in: query\n" + " schema:\n" + " type: string\n" + " - name: x-authorized-by\n" + " in: header\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SimpleResponse\"\n" + "components:\n" + " schemas:\n" + " SimpleResponse:\n" + " type: object\n"); } static class MethodWithParameters { @GET @Operation(description = "method with parameters") @Path("/findAll") public SimpleResponse getSimpleResponseWithParameters( @QueryParam("id") String id, @HeaderParam("x-authorized-by") String[] auth) { return null; } } @Test(description = "shows how annotations can decorate an operation") public void testPartiallyAnnotatedMethod() { String yaml = readIntoYaml(MethodWithPartialAnnotation.class); String expectedYaml = "openapi: 3.0.1\n" + "paths:\n" + " /findAll:\n" + " get:\n" + " description: returns a value\n" + " operationId: getSimpleResponseWithParameters\n" + " parameters:\n" + " - name: id\n" + " in: query\n" + " schema:\n" + " pattern: \"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\"\n" + " type: string\n" + " description: a GUID for the user in uuid-v4 format\n" + " format: uuid\n" + " - name: x-authorized-by\n" + " in: header\n" + " schema:\n" + " type: array\n" + " items:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SimpleResponse\"\n" + "components:\n" + " schemas:\n" + " SimpleResponse:\n" + " type: object\n"; assertEquals(yaml, expectedYaml); } static class MethodWithPartialAnnotation { @GET @Operation(description = "returns a value") @Path("/findAll") public SimpleResponse getSimpleResponseWithParameters( @Schema( description = "a GUID for the user in uuid-v4 format", required = true, format = "uuid", pattern = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}") @QueryParam("id") String id, @HeaderParam("x-authorized-by") String[] auth) { return null; } } @Test(description = "shows how a request body is passed") public void testRequestBody() { String yaml = readIntoYaml(MethodWithRequestBody.class); String expectedYaml = "openapi: 3.0.1\n" + "paths:\n" + " /add:\n" + " post:\n" + " description: receives a body\n" + " operationId: addValue\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/InputValue\"\n" + " responses:\n" + " \"201\":\n" + " description: value successfully processed\n" + "components:\n" + " schemas:\n" + " InputValue:\n" + " type: object\n"; assertEquals(yaml, expectedYaml); } static class MethodWithRequestBody { @POST @Operation(description = "receives a body", responses = @ApiResponse( responseCode = "201", description = "value successfully processed") ) @Path("/add") public void addValue(InputValue input) { } } static class InputValue { private Long id; private String name; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/parameters/ParametersTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.parameters; import io.swagger.v3.jaxrs2.Reader; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.jaxrs2.resources.ResourceWithJacksonBean; import io.swagger.v3.jaxrs2.resources.ResourceWithKnownInjections; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.models.OpenAPI; import org.testng.annotations.Test; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class ParametersTest extends AbstractAnnotationTest { @Test(description = "scan class level and field level annotations") public void scanClassAndFieldLevelAnnotations() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ResourceWithKnownInjections.class); List resourceParameters = openAPI.getPaths().get("/resource/{id}").getGet().getParameters(); assertNotNull(resourceParameters); assertEquals(resourceParameters.size(), 3); assertEquals(resourceParameters.get(0).getName(), "id"); assertEquals(resourceParameters.get(1).getName(), "fieldParam"); assertEquals(resourceParameters.get(2).getName(), "methodParam"); } @Test public void testParameters() { String openApiYAML = readIntoYaml(ParametersTest.SimpleOperations.class); int start = openApiYAML.indexOf("/test:"); int end = openApiYAML.length() - 1; String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "/test:\n" + " post:\n" + " description: \"subscribes a client to updates relevant to the requestor's account,\\\n" + " \\ as identified by the input token. The supplied url will be used as the\\\n" + " \\ delivery address for response payloads\"\n" + " operationId: subscribe\n" + " parameters:\n" + " - name: subscriptionId\n" + " in: path\n" + " required: true\n" + " style: simple\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " - name: formId\n" + " in: query\n" + " required: true\n" + " schema:\n" + " type: string\n" + " example: Example\n" + " - name: explodeFalse\n" + " in: query\n" + " required: true\n" + " explode: false\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " - name: explodeTrue\n" + " in: query\n" + " required: true\n" + " explode: true\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " - name: explodeAvoiding\n" + " in: query\n" + " required: true\n" + " schema:\n" + " type: string\n" + " description: the generated id\n" + " format: id\n" + " readOnly: true\n" + " - name: arrayParameter\n" + " in: query\n" + " required: true\n" + " explode: true\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: number\n" + " description: the generated id\n" + " readOnly: true\n" + " application/xml:\n" + " schema:\n" + " type: number\n" + " description: the generated id\n" + " readOnly: true\n" + " - name: arrayParameterImplementation\n" + " in: query\n" + " required: true\n" + " explode: true\n" + " schema:\n" + " maxItems: 10\n" + " minItems: 1\n" + " uniqueItems: true\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " - name: arrayParameterImplementation2\n" + " in: query\n" + " required: true\n" + " explode: true\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + "components:\n" + " schemas:\n" + " SubscriptionResponse:\n" + " type: object\n" + " properties:\n" + " subscriptionId:\n" + " type: string"; assertEquals(extractedYAML, expectedYAML); } @Test public void testArraySchemaParameters() { String openApiYAML = readIntoYaml(ParametersTest.ArraySchemaOperations.class); int start = openApiYAML.indexOf("/test:"); int end = openApiYAML.length() - 1; String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "/test:\n" + " post:\n" + " description: \"subscribes a client to updates relevant to the requestor's account,\\\n" + " \\ as identified by the input token. The supplied url will be used as the\\\n" + " \\ delivery address for response payloads\"\n" + " operationId: subscribe\n" + " parameters:\n" + " - name: arrayParameter\n" + " in: query\n" + " required: true\n" + " explode: true\n" + " schema:\n" + " maxItems: 10\n" + " minItems: 1\n" + " uniqueItems: true\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + "components:\n" + " schemas:\n" + " SubscriptionResponse:\n" + " type: object\n" + " properties:\n" + " subscriptionId:\n" + " type: string"; assertEquals(extractedYAML, expectedYAML); } @Test public void testRepeatableParameters() { String openApiYAML = readIntoYaml(ParametersTest.RepeatableParametersOperations.class); int start = openApiYAML.indexOf("/test:"); int end = openApiYAML.length() - 1; String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "/test:\n" + " post:\n" + " description: \"subscribes a client to updates relevant to the requestor's account,\\\n" + " \\ as identified by the input token. The supplied url will be used as the\\\n" + " \\ delivery address for response payloads\"\n" + " operationId: subscribe\n" + " parameters:\n" + " - name: subscriptionId\n" + " in: path\n" + " required: true\n" + " style: simple\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " - name: formId\n" + " in: query\n" + " required: true\n" + " schema:\n" + " type: string\n" + " example: Example\n" + " - name: explodeFalse\n" + " in: query\n" + " required: true\n" + " explode: false\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " - name: explodeTrue\n" + " in: query\n" + " required: true\n" + " explode: true\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " - name: explodeAvoiding\n" + " in: query\n" + " required: true\n" + " schema:\n" + " type: string\n" + " description: the generated id\n" + " format: id\n" + " readOnly: true\n" + " - name: arrayParameter\n" + " in: query\n" + " required: true\n" + " explode: true\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: number\n" + " description: the generated id\n" + " readOnly: true\n" + " application/xml:\n" + " schema:\n" + " type: number\n" + " description: the generated id\n" + " readOnly: true\n" + " - name: arrayParameterImplementation\n" + " in: query\n" + " required: true\n" + " explode: true\n" + " schema:\n" + " maxItems: 10\n" + " minItems: 1\n" + " uniqueItems: true\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " - name: arrayParameterImplementation2\n" + " in: query\n" + " required: true\n" + " explode: true\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/SubscriptionResponse\"\n" + "components:\n" + " schemas:\n" + " SubscriptionResponse:\n" + " type: object\n" + " properties:\n" + " subscriptionId:\n" + " type: string"; assertEquals(extractedYAML, expectedYAML); } @Test(description = "JsonUnwrapped, JsonIgnore, JsonValue should be honoured") public void testJacksonFeatures() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(ResourceWithJacksonBean.class); io.swagger.v3.oas.models.media.Schema o = openAPI.getComponents().getSchemas().get("JacksonBean"); assertEquals(o.getProperties().keySet(), Stream.of("identity", "bean", "code", "message", "precodesuf", "premessagesuf").collect(Collectors.toSet())); } static class SimpleOperations { @Path("/test") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class), style = ParameterStyle.SIMPLE), @Parameter(in = ParameterIn.QUERY, name = "formId", required = true, example = "Example"), @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class)), @Parameter(in = ParameterIn.QUERY, name = "explodeTrue", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class)), @Parameter(in = ParameterIn.QUERY, name = "explodeAvoiding", required = true, explode = Explode.TRUE, schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY )), @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class), uniqueItems = true ) , schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY), content = @Content(schema = @Schema(type = "number", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY)) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class), uniqueItems = true ) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation2", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class)) }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersTest.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersTest.SubscriptionResponse subscribe() { return null; } } static class ArraySchemaOperations { @Path("/test") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class), uniqueItems = true ) ), }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersTest.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersTest.SubscriptionResponse subscribe() { return null; } } static class RepeatableParametersOperations { @Path("/test") @POST @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class), style = ParameterStyle.SIMPLE) @Parameter(in = ParameterIn.QUERY, name = "formId", required = true, example = "Example") @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class)) @Parameter(in = ParameterIn.QUERY, name = "explodeTrue", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class)) @Parameter(in = ParameterIn.QUERY, name = "explodeAvoiding", required = true, explode = Explode.TRUE, schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY )) @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class), uniqueItems = true ) , schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY), content = @Content(schema = @Schema(type = "number", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY)) ) @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class), uniqueItems = true ) ) @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation2", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersTest.SubscriptionResponse.class)) @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersTest.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersTest.SubscriptionResponse subscribe() { return null; } } static class SubscriptionResponse { public String subscriptionId; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/pathItems/OperationsWithLinksTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.pathItems; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.testng.annotations.Test; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import java.io.IOException; import static org.testng.Assert.assertEquals; public class OperationsWithLinksTest extends AbstractAnnotationTest { @Test(description = "Shows creating simple links") public void createOperationWithLinks() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /users:\n" + " get:\n" + " operationId: getUser\n" + " parameters:\n" + " - name: userId\n" + " in: query\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " links:\n" + " address:\n" + " operationId: getAddress\n" + " parameters:\n" + " userId: $request.query.userId\n" + " /addresses:\n" + " get:\n" + " operationId: getAddress\n" + " parameters:\n" + " - name: userId\n" + " in: query\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Address\"\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " username:\n" + " type: string\n" + " Address:\n" + " type: object\n" + " properties:\n" + " street:\n" + " type: string\n" + " zip:\n" + " type: string"; compareAsYaml(ClassWithOperationAndLinks.class, expectedYAML); } @Test(description = "Shows creating simple links with request body") public void createOperationWithLinksAndRequestBody() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /users:\n" + " get:\n" + " operationId: getUser\n" + " parameters:\n" + " - name: userId\n" + " in: query\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " links:\n" + " address:\n" + " operationId: addAddress\n" + " requestBody: $request.query.userId\n" + " /addresses:\n" + " post:\n" + " operationId: addAddress\n" + " requestBody:\n" + " description: userId\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " type: string\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Address\"\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " username:\n" + " type: string\n" + " Address:\n" + " type: object\n" + " properties:\n" + " street:\n" + " type: string\n" + " zip:\n" + " type: string"; compareAsYaml(ClassWithOperationAndLinksWithRequestBody.class, expectedYAML); } @Test(description = "Shows creating operation response without annotation") public void createOperationWithResponseNoAnnotation() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /users:\n" + " get:\n" + " operationId: getUser\n" + " parameters:\n" + " - name: userId\n" + " in: query\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " username:\n" + " type: string"; compareAsYaml(ClassWithResponseNoAnnotation.class, expectedYAML); } static class ClassWithOperationAndLinks { @Path("/users") @Operation(operationId = "getUser", responses = { @ApiResponse(description = "test description", content = @Content(mediaType = "*/*", schema = @Schema(ref = "#/components/schemas/User")), links = { @Link( name = "address", operationId = "getAddress", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) })} ) @GET public User getUser(@QueryParam("userId") String userId) { return null; } @Path("/addresses") @Operation(operationId = "getAddress", responses = { @ApiResponse(content = @Content(mediaType = "*/*", schema = @Schema(ref = "#/components/schemas/Address")), description = "test description") }) @GET public Address getAddress(@QueryParam("userId") String userId) { return null; } } static class ClassWithOperationAndLinksWithRequestBody { @Path("/users") @Operation(operationId = "getUser", responses = { @ApiResponse(description = "test description", content = @Content(mediaType = "*/*", schema = @Schema(ref = "#/components/schemas/User")), links = { @Link( name = "address", operationId = "addAddress", requestBody = "$request.query.userId") })} ) @GET public User getUser(@QueryParam("userId") String userId) { return null; } @Path("/addresses") @Operation(operationId = "addAddress", responses = { @ApiResponse(content = @Content(mediaType = "*/*", schema = @Schema(ref = "#/components/schemas/Address")), description = "test description") }) @POST public Address addAddress(@RequestBody(description = "userId", required = true) String userId) { return null; } } static class ClassWithResponseNoAnnotation { @Path("/users") @Operation(operationId = "getUser") @GET public User getUser(@QueryParam("userId") String userId) { return null; } } static class User { private String id; private String username; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } } static class Address { private String street; private String zip; public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; } } @Test(description = "Shows creating simple links") public void createOperationWithLinkReferences() { String openApiYAML = readIntoYaml(ClassWithOperationAndLinkReferences.class); int start = openApiYAML.indexOf("/users:"); int end = openApiYAML.length() - 1; String expectedYaml = "/users:\n" + " get:\n" + " operationId: getUser\n" + " parameters:\n" + " - name: userId\n" + " in: query\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: test description\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " links:\n" + " user:\n" + " operationId: getUser\n" + " parameters:\n" + " userId: $request.query.userId\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " username:\n" + " type: string"; String extractedYAML = openApiYAML.substring(start, end); assertEquals(extractedYAML, expectedYaml); } static class ClassWithOperationAndLinkReferences { @Path("/users") @Operation(operationId = "getUser", responses = { @ApiResponse(description = "test description", links = { @Link( name = "user", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) })} ) @GET public User getUser(@QueryParam("userId") String userId) { return null; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/readerListener/ReaderListenerTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.readerListener; import io.swagger.v3.jaxrs2.Reader; import io.swagger.v3.jaxrs2.resources.ReaderListenerResource; import io.swagger.v3.oas.models.OpenAPI; import org.testng.annotations.Test; import java.util.Collections; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class ReaderListenerTest { @Test(description = "test a readerListener resource") public void testReaderListener() throws Exception { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(Collections.singleton(ReaderListenerResource.class)); assertNotNull(openAPI); assertEquals(openAPI.getTags().get(0).getName(), "Tag-added-before-read"); assertEquals(openAPI.getTags().get(1).getName(), "Tag-added-after-read"); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/requests/RequestBodyTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.requests; import io.swagger.v3.jaxrs2.Reader; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.jaxrs2.it.resources.MultiPartFileResource; import io.swagger.v3.jaxrs2.it.resources.OctetStreamResource; import io.swagger.v3.jaxrs2.it.resources.UrlEncodedResource; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.PathItem; import org.testng.annotations.Test; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.PATCH; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import java.io.IOException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public class RequestBodyTest extends AbstractAnnotationTest { private static final String REQUEST_BODY_IN_METHOD = "RequestBody in Method"; private static final String REQUEST_BODY_IN_PARAMETER = "Request Body in Param"; private static final String NO_IN_PARAMETER = "Parameter with no IN"; private static final String REQUEST_BODY_IN_ANNOTATION = "RequestBody in Annotation"; private static final String USER_PATH = "/user"; @Test(description = "Returns a request with one RequestBody and multiple parameters") public void oneRequestBodyMultipleParameters() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /user:\n" + " put:\n" + " summary: Modify user\n" + " description: Modifying user.\n" + " operationId: methodWithRequestBodyWithoutAnnotation\n" + " requestBody:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " post:\n" + " summary: Create user\n" + " description: This can only be done by the logged in user.\n" + " operationId: methodWithRequestBodyAndTwoParameters\n" + " parameters:\n" + " - name: name\n" + " in: query\n" + " schema:\n" + " type: string\n" + " - name: code\n" + " in: query\n" + " schema:\n" + " type: string\n" + " requestBody:\n" + " description: Created user object\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " required: true\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " delete:\n" + " summary: Delete user\n" + " description: This can only be done by the logged in user.\n" + " operationId: methodWithoutRequestBodyAndTwoParameters\n" + " parameters:\n" + " - name: name\n" + " in: query\n" + " schema:\n" + " type: string\n" + " - name: code\n" + " in: query\n" + " schema:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " /pet:\n" + " put:\n" + " summary: Modify pet\n" + " description: Modifying pet.\n" + " operationId: methodWithRequestBodyWithoutAnnotationAndTwoConsumes\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/User\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " post:\n" + " summary: Create pet\n" + " description: Creating pet.\n" + " operationId: methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " application/xml:\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " delete:\n" + " summary: Delete pet\n" + " description: Deleting pet.\n" + " operationId: methodWithOneSimpleRequestBody\n" + " requestBody:\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " application/xml:\n" + " schema:\n" + " type: integer\n" + " format: int32\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + "components:\n" + " schemas:\n" + " User:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " username:\n" + " type: string\n" + " firstName:\n" + " type: string\n" + " lastName:\n" + " type: string\n" + " email:\n" + " type: string\n" + " password:\n" + " type: string\n" + " phone:\n" + " type: string\n" + " userStatus:\n" + " type: integer\n" + " description: User Status\n" + " format: int32\n" + " xml:\n" + " name: User\n" + " Category:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Category\n" + " Tag:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Tag\n" + " Pet:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " category:\n" + " $ref: \"#/components/schemas/Category\"\n" + " name:\n" + " type: string\n" + " photoUrls:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " type: string\n" + " xml:\n" + " name: photoUrl\n" + " tags:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " $ref: \"#/components/schemas/Tag\"\n" + " status:\n" + " type: string\n" + " description: pet status in the store\n" + " enum:\n" + " - available,pending,sold\n" + " xml:\n" + " name: Pet"; compareAsYaml(RequestBodyTest.UserResource.class, expectedYAML); } static class UserResource { @POST @Path("/user") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyAndTwoParameters( @RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema(implementation = User.class))) User user, @QueryParam("name") String name, @QueryParam("code") String code) { return Response.ok().entity("").build(); } @PUT @Path("/user") @Operation(summary = "Modify user", description = "Modifying user.") public Response methodWithRequestBodyWithoutAnnotation( User user) { return Response.ok().entity("").build(); } @DELETE @Path("/user") @Operation(summary = "Delete user", description = "This can only be done by the logged in user.") public Response methodWithoutRequestBodyAndTwoParameters( @QueryParam("name") String name, @QueryParam("code") String code) { return Response.ok().entity("").build(); } @PUT @Path("/pet") @Operation(summary = "Modify pet", description = "Modifying pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithRequestBodyWithoutAnnotationAndTwoConsumes( User user) { return Response.ok().entity("").build(); } @POST @Path("/pet") @Operation(summary = "Create pet", description = "Creating pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes( Pet pet, User user) { return Response.ok().entity("").build(); } @DELETE @Path("/pet") @Operation(summary = "Delete pet", description = "Deleting pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithOneSimpleRequestBody(int id) { return Response.ok().entity("").build(); } } @Test(description = "scan class with requesbody annotation") public void testRequestBodyAnnotationPriority() { Reader reader = new Reader(new OpenAPI()); OpenAPI openAPI = reader.read(RequestBodyResource.class); PathItem userPathItem = openAPI.getPaths().get(USER_PATH); io.swagger.v3.oas.models.parameters.RequestBody getRequestBody = userPathItem.getGet().getRequestBody(); assertNotNull(getRequestBody); assertEquals(getRequestBody.getDescription(), REQUEST_BODY_IN_ANNOTATION); io.swagger.v3.oas.models.parameters.RequestBody postRequestBody = userPathItem.getPost().getRequestBody(); assertNotNull(postRequestBody); assertEquals(postRequestBody.getDescription(), REQUEST_BODY_IN_ANNOTATION); io.swagger.v3.oas.models.parameters.RequestBody putRequestBody = userPathItem.getPut().getRequestBody(); assertNotNull(putRequestBody); assertEquals(putRequestBody.getDescription(), REQUEST_BODY_IN_METHOD); io.swagger.v3.oas.models.parameters.RequestBody deleteRequestBody = userPathItem.getDelete().getRequestBody(); assertNotNull(deleteRequestBody); assertEquals(deleteRequestBody.getDescription(), REQUEST_BODY_IN_METHOD); io.swagger.v3.oas.models.parameters.RequestBody patchRequestBody = userPathItem.getPatch().getRequestBody(); assertNotNull(patchRequestBody); assertEquals(patchRequestBody.getDescription(), REQUEST_BODY_IN_METHOD); userPathItem = openAPI.getPaths().get(USER_PATH + "/deleteUserMethod_Param_RequestBody"); deleteRequestBody = userPathItem.getDelete().getRequestBody(); assertNotNull(deleteRequestBody); assertEquals(deleteRequestBody.getDescription(), REQUEST_BODY_IN_PARAMETER); userPathItem = openAPI.getPaths().get(USER_PATH + "/deleteUserOperation_Method_Param_RequestBody"); deleteRequestBody = userPathItem.getDelete().getRequestBody(); assertNotNull(deleteRequestBody); assertEquals(deleteRequestBody.getDescription(), REQUEST_BODY_IN_PARAMETER); userPathItem = openAPI.getPaths().get(USER_PATH + "/deleteUserOperation_RequestBody"); deleteRequestBody = userPathItem.getDelete().getRequestBody(); assertNotNull(deleteRequestBody); assertEquals(deleteRequestBody.getDescription(), REQUEST_BODY_IN_PARAMETER); userPathItem = openAPI.getPaths().get(USER_PATH + "/deleteUserOperation_Method_Param"); deleteRequestBody = userPathItem.getDelete().getRequestBody(); assertNotNull(deleteRequestBody); assertEquals(deleteRequestBody.getDescription(), REQUEST_BODY_IN_METHOD); } @Path("/user") static class RequestBodyResource { @GET @Operation(requestBody = @RequestBody(description = "RequestBody in Annotation", required = true, content = @Content(schema = @Schema(implementation = User.class)))) public User getUser() { return new User(); } @POST @Operation(summary = "Create user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "RequestBody in Annotation", required = true, content = @Content(schema = @Schema(implementation = User.class)))) public Response createUser( @Parameter(description = "Parameter with no IN", required = true) User user) { return Response.ok().entity("").build(); } @PUT @Operation(summary = "Update user", description = "This can only be done by the logged in user.") @RequestBody(description = "RequestBody in Method", required = true, content = @Content(schema = @Schema(implementation = User.class))) public Response updateUser() { return Response.ok().entity("").build(); } @DELETE @Operation(summary = "Delete user", description = "This can only be done by the logged in user.") @RequestBody(description = "RequestBody in Method", required = true, content = @Content(schema = @Schema(implementation = User.class))) public Response deleteUser(@Parameter(description = "Parameter with no IN", required = true) User user) { return Response.ok().entity("").build(); } @DELETE @Path("/deleteUserMethod_Param_RequestBody") @Operation(summary = "Delete user", description = "This can only be done by the logged in user.") @RequestBody(description = "RequestBody in Method", required = true, content = @Content(schema = @Schema(implementation = User.class))) public Response deleteUserMethod_Param_RequestBody( @Parameter(description = "Parameter with no IN", required = true) @RequestBody(description = "Request Body in Param") User user) { return Response.ok().entity("").build(); } @DELETE @Path("/deleteUserOperation_Method_Param_RequestBody") @Operation(summary = "Delete user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "RequestBody in Annotation", required = true, content = @Content(schema = @Schema(implementation = User.class)))) @RequestBody(description = "RequestBody in Method", required = true, content = @Content(schema = @Schema(implementation = User.class))) public Response deleteUserOperation_Method_Param_RequestBody( @Parameter(description = "Parameter with no IN", required = true) @RequestBody(description = "Request Body in Param") User user) { return Response.ok().entity("").build(); } @DELETE @Path("/deleteUserOperation_Method_Param") @Operation(summary = "Delete user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "RequestBody in Annotation", required = true, content = @Content(schema = @Schema(implementation = User.class)))) @RequestBody(description = "RequestBody in Method", required = true, content = @Content(schema = @Schema(implementation = User.class))) public Response deleteUserOperation_Method_Param( @Parameter(description = "Parameter with no IN", required = true) User user) { return Response.ok().entity("").build(); } @DELETE @Path("/deleteUserOperation_RequestBody") @Operation(summary = "Delete user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "RequestBody in Annotation", required = true, content = @Content(schema = @Schema(implementation = User.class)))) public Response deleteUserOperation_RequestBody( @RequestBody(description = "Request Body in Param") User user) { return Response.ok().entity("").build(); } @PATCH @Operation(summary = "Modify user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "RequestBody in Annotation", required = true, content = @Content(schema = @Schema(implementation = User.class)))) @RequestBody(description = "RequestBody in Method", required = true, content = @Content(schema = @Schema(implementation = User.class))) public Response modifyUser() { return Response.ok().entity("").build(); } } @Test(description = "Test file upload") public void testFileUploadOctetStream() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /files/attach:\n" + " put:\n" + " operationId: putFile\n" + " requestBody:\n" + " content:\n" + " application/octet-stream:\n" + " schema:\n" + " type: string\n" + " format: binary\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}"; compareAsYaml(OctetStreamResource.class, expectedYAML); } @Test(description = "Test urlencoded") public void testUrlEncoded() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /users/add:\n" + " post:\n" + " operationId: addUser\n" + " requestBody:\n" + " content:\n" + " application/x-www-form-urlencoded:\n" + " schema:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " name:\n" + " type: string\n" + " gender:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}"; compareAsYaml(UrlEncodedResource.class, expectedYAML); } @Test(description = "Test multipart") public void testMultiPart() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /files/upload:\n" + " post:\n" + " operationId: uploadFile\n" + " requestBody:\n" + " content:\n" + " multipart/form-data:\n" + " schema:\n" + " type: object\n" + " properties:\n" + " fileIdRenamed:\n" + " type: string\n" + " fileRenamed:\n" + " type: string\n" + " format: binary\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n"; compareAsYaml(MultiPartFileResource.class, expectedYAML); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/annotations/security/SecurityTest.java ================================================ package io.swagger.v3.jaxrs2.annotations.security; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import io.swagger.v3.jaxrs2.resources.SecurityResource; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.security.OAuthFlow; import io.swagger.v3.oas.annotations.security.OAuthFlows; import io.swagger.v3.oas.annotations.security.OAuthScope; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityRequirementEntry; import io.swagger.v3.oas.annotations.security.SecurityScheme; import org.testng.annotations.Test; import java.io.IOException; import static org.testng.Assert.assertEquals; public class SecurityTest extends AbstractAnnotationTest { @Test public void testSecurityScheme() { String openApiYAML = readIntoYaml(SecurityTest.OAuth2SchemeOnClass.class); int start = openApiYAML.indexOf("components:"); String extractedYAML = openApiYAML.substring(start, openApiYAML.length() - 1); String expectedYAML = "components:\n" + " securitySchemes:\n" + " myOauth2Security:\n" + " type: oauth2\n" + " in: header\n" + " flows:\n" + " implicit:\n" + " authorizationUrl: http://url.com/auth\n" + " scopes:\n" + " write:pets: modify pets in your account"; assertEquals(extractedYAML, expectedYAML); } @Test public void testSecurityRequirement() throws IOException { String expectedYAML = "openapi: 3.0.1\n" + "paths:\n" + " /2:\n" + " get:\n" + " description: description 2\n" + " operationId: Operation Id 2\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " security:\n" + " - security_key:\n" + " - write:pets\n" + " - read:pets\n" + " - myOauth2Security:\n" + " - write:pets\n" + " - security_key2:\n" + " - write:pets\n" + " - read:pets\n" + " /:\n" + " get:\n" + " description: description\n" + " operationId: Operation Id\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " security:\n" + " - security_key:\n" + " - write:pets\n" + " - read:pets\n" + " - myOauth2Security:\n" + " - write:pets\n" + "components:\n" + " securitySchemes:\n" + " myOauth2Security:\n" + " type: oauth2\n" + " description: myOauthSecurity Description\n" + " in: header\n" + " flows:\n" + " implicit:\n" + " authorizationUrl: http://x.com\n" + " scopes:\n" + " write:pets: modify pets in your account"; compareAsYaml(SecurityResource.class, expectedYAML); } @Test public void testMultipleSecuritySchemes() { String openApiYAML = readIntoYaml(SecurityTest.MultipleSchemesOnClass.class); int start = openApiYAML.indexOf("components:"); String extractedYAML = openApiYAML.substring(start, openApiYAML.length() - 1); String expectedYAML = "components:\n" + " securitySchemes:\n" + " apiKey:\n" + " type: apiKey\n" + " name: API_KEY\n" + " in: header\n" + " myOauth2Security:\n" + " type: oauth2\n" + " in: header\n" + " flows:\n" + " implicit:\n" + " authorizationUrl: http://url.com/auth\n" + " scopes:\n" + " write:pets: modify pets in your account"; assertEquals(extractedYAML, expectedYAML); } @Test public void testCombinedSecurityRequirements() { String openApiYAML = readIntoYaml(SecurityTest.CombinedSecurityRequirementsOnClass.class); int start = openApiYAML.indexOf("security:"); int end = openApiYAML.indexOf("components:"); String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "security:\n" + "- api_key: []\n" + " myOauth2Security: []\n"; assertEquals(extractedYAML, expectedYAML); } @Test public void testSecurityRequirementAlternatives() { String openApiYAML = readIntoYaml(SecurityRequirementAlternativesOnClass.class); int start = openApiYAML.indexOf("security:"); int end = openApiYAML.indexOf("components:"); String extractedYAML = openApiYAML.substring(start, end); String expectedYAML = "security:\n" + "- api_key: []\n" + "- myOauth2Security: []\n"; assertEquals(extractedYAML, expectedYAML); } @Test public void testTicket2767() { String openApiYAML = readIntoYaml(SecurityTest.Ticket2767.class); String expectedYAML = "openapi: 3.0.1\n" + "info:\n" + " title: Test\n" + " version: 1.0-SNAPSHOT\n" + "security:\n" + "- basicAuth: []\n" + "components:\n" + " securitySchemes:\n" + " basicAuth:\n" + " type: http\n" + " scheme: basic\n"; assertEquals(openApiYAML, expectedYAML); } @Test public void testTicket2767_2() { String openApiYAML = readIntoYaml(SecurityTest.Ticket2767_2.class); String expectedYAML = "openapi: 3.0.1\n" + "info:\n" + " title: Test\n" + " version: 1.0-SNAPSHOT\n" + "security:\n" + "- api_key: []\n" + "components:\n" + " securitySchemes:\n" + " api_key:\n" + " type: apiKey\n" + " name: API_KEY\n"; assertEquals(openApiYAML, expectedYAML); } @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, flows = @OAuthFlows( implicit = @OAuthFlow(authorizationUrl = "http://url.com/auth", scopes = @OAuthScope(name = "write:pets", description = "modify pets in your account")))) static class OAuth2SchemeOnClass { } @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, flows = @OAuthFlows( implicit = @OAuthFlow(authorizationUrl = "http://url.com/auth", scopes = @OAuthScope(name = "write:pets", description = "modify pets in your account")))) @SecurityScheme(name = "apiKey", type = SecuritySchemeType.APIKEY, in = SecuritySchemeIn.HEADER, paramName = "API_KEY") static class MultipleSchemesOnClass { } @OpenAPIDefinition( security = {@SecurityRequirement(combine = { @SecurityRequirementEntry(name = "api_key"), @SecurityRequirementEntry(name = "myOauth2Security") })} ) @SecurityScheme(name = "api_key", type = SecuritySchemeType.APIKEY, paramName = "API_KEY") @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, flows = @OAuthFlows( implicit = @OAuthFlow(authorizationUrl = "http://url.com/auth", scopes = @OAuthScope(name = "write:pets", description = "modify pets in your account")))) static class CombinedSecurityRequirementsOnClass { } @OpenAPIDefinition( security = {@SecurityRequirement(name = "api_key"), @SecurityRequirement(name = "myOauth2Security")} ) @SecurityScheme(name = "api_key", type = SecuritySchemeType.APIKEY, paramName = "API_KEY") @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, flows = @OAuthFlows( implicit = @OAuthFlow(authorizationUrl = "http://url.com/auth", scopes = @OAuthScope(name = "write:pets", description = "modify pets in your account")))) static class SecurityRequirementAlternativesOnClass { } @OpenAPIDefinition( security = {@SecurityRequirement(name = "basicAuth")}, info = @Info( title = "Test", description = "", version = "1.0-SNAPSHOT")) @SecurityScheme(name="basicAuth", type = SecuritySchemeType.HTTP, scheme = "basic") static class Ticket2767 { } @OpenAPIDefinition( security = {@SecurityRequirement(name = "api_key")}, info = @Info( title = "Test", description = "", version = "1.0-SNAPSHOT")) @SecurityScheme(name="api_key", type = SecuritySchemeType.APIKEY, paramName = "API_KEY") static class Ticket2767_2 { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/cdi2/CDIAutodiscoveryTest.java ================================================ package io.swagger.v3.jaxrs2.cdi2; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.testng.Arquillian; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.testng.AssertJUnit; import org.testng.annotations.Test; import io.swagger.v3.jaxrs2.SwaggerSerializers; import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource; import javax.enterprise.inject.spi.Extension; import javax.inject.Inject; public class CDIAutodiscoveryTest extends Arquillian { @Inject DiscoveryTestExtension ext; @Deployment public static JavaArchive createDeployment() { return ShrinkWrap.create(JavaArchive.class) .addClasses(SwaggerSerializers.class) .addPackage(OpenApiResource.class.getPackage()) .addAsServiceProviderAndClasses(Extension.class, DiscoveryTestExtension.class) .addAsManifestResource("META-INF/beans.xml"); } @Test void confirmPathClassesWereDiscovered() { String[] expected = { "io.swagger.v3.jaxrs2.integration.resources.AcceptHeaderOpenApiResource", "io.swagger.v3.jaxrs2.integration.resources.OpenApiResource" }; Object[] found = ext.getResources().stream() .map(resource -> resource.getName()) .sorted() .toArray(); AssertJUnit.assertArrayEquals(expected, found); } @Test void confirmProviderClassesWereDiscovered() { String[] expected = { "io.swagger.v3.jaxrs2.SwaggerSerializers" }; Object[] found = ext.getProviders().stream() .map(resource -> resource.getName()) .toArray(); AssertJUnit.assertArrayEquals(expected, found); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/cdi2/DiscoveryTestExtension.java ================================================ package io.swagger.v3.jaxrs2.cdi2; import java.util.HashSet; import java.util.Set; import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessAnnotatedType; import javax.enterprise.inject.spi.WithAnnotations; import javax.ws.rs.Path; import javax.ws.rs.ext.Provider; public class DiscoveryTestExtension implements Extension { private final Set> providers = new HashSet<>(); private final Set> resources = new HashSet<>(); public Set> getProviders() { return providers; } public Set> getResources() { return resources; } public void observeResources(@WithAnnotations({ Path.class }) @Observes ProcessAnnotatedType event) { AnnotatedType annotatedType = event.getAnnotatedType(); if (!annotatedType.getJavaClass().isInterface()) { this.resources.add(annotatedType.getJavaClass()); } } public void observeProviders(@WithAnnotations({ Provider.class }) @Observes ProcessAnnotatedType event) { AnnotatedType annotatedType = event.getAnnotatedType(); if (!annotatedType.getJavaClass().isInterface()) { this.providers.add(annotatedType.getJavaClass()); } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/integration/JaxrsApplicationAndAnnotationScannerTest.java ================================================ package io.swagger.v3.jaxrs2.integration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Application; import org.my.project.resources.ResourceInPackageB; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.my.project.resources.ResourceInPackageA; import io.swagger.v3.jaxrs2.Reader; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.integration.GenericOpenApiContext; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class JaxrsApplicationAndAnnotationScannerTest { private JaxrsApplicationAndAnnotationScanner scanner; @Path("/app") protected static class ResourceInApplication { @Operation(operationId = "test.") @GET public void getTest(@Parameter(name = "test") ArrayList tenantId) { return; } } @BeforeMethod public void setUp() { scanner = new JaxrsApplicationAndAnnotationScanner(); scanner.setApplication(new Application() { @Override public Set> getClasses() { return Collections.singleton(ResourceInApplication.class); } }); } @Test(description = "scan classes from all packages and Application") public void shouldScanClassesFromAllPackagesAndApplication() throws Exception { assertTrue(scanner.classes().contains(ResourceInPackageA.class)); assertTrue(scanner.classes().contains(ResourceInPackageB.class)); assertTrue(scanner.classes().contains(ResourceInApplication.class)); } @Test(description = "scan classes from the packages and Application") public void shouldScanClassesFromPackagesAndApplication() throws Exception { SwaggerConfiguration openApiConfiguration = new SwaggerConfiguration(); openApiConfiguration.setResourcePackages(Collections.singleton("com.my.project.resources")); scanner.setConfiguration(openApiConfiguration); assertEquals(scanner.classes().size(), 2); assertTrue(scanner.classes().contains(ResourceInPackageA.class)); assertTrue(scanner.classes().contains(ResourceInApplication.class)); } @Test(description = "scan a simple resource from packages") public void shouldScanClassesFromPackages() throws Exception { SwaggerConfiguration config = new SwaggerConfiguration() .resourcePackages(Stream.of("com.my.project.resources", "org.my.project.resources").collect(Collectors.toSet())) .openAPI(new OpenAPI().info(new Info().description("TEST INFO DESC"))); OpenApiContext ctx = new GenericOpenApiContext<>() .openApiConfiguration(config) .openApiReader(new Reader(config)) .openApiScanner(scanner.application(null).openApiConfiguration(config)) .init(); OpenAPI openApi = ctx.read(); assertNotNull(openApi); assertEquals(openApi.getPaths().keySet(), Arrays.asList("/packageA", "/packageB")); } @Test(description = "scan a simple resource from packages using configuration file") public void shouldScanClassesFromPackagesUsingConfigurationFile() throws Exception { String configPath = "/integration/openapi-configuration.json"; OpenApiContext ctx = new XmlWebOpenApiContext<>().configLocation(configPath).init(); OpenAPI openApi = ctx.read(); assertNotNull(openApi); assertEquals(openApi.getPaths().keySet(), Arrays.asList("/packageA", "/packageB")); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/integration/JaxrsApplicationAndResourcePackagesAnnotationScannerTest.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.swagger.v3.jaxrs2.Reader; import io.swagger.v3.oas.integration.GenericOpenApiContext; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.my.project.resources.ResourceInPackageA; import java.util.Arrays; import java.util.Collections; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.ws.rs.core.Application; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; public class JaxrsApplicationAndResourcePackagesAnnotationScannerTest { private JaxrsApplicationAndResourcePackagesAnnotationScanner scanner; @BeforeMethod public void setUp() { scanner = new JaxrsApplicationAndResourcePackagesAnnotationScanner(); } @Test(description = "scan classes from resource packages only") public void shouldScanOnlyResourcePackagesClasses() throws Exception { SwaggerConfiguration config = new SwaggerConfiguration() .resourcePackages(Stream.of("com.my.project.resources", "org.my.project.resources").collect(Collectors.toSet())) .openAPI(new OpenAPI().info(new Info().description("TEST INFO DESC"))); OpenApiContext ctx = new GenericOpenApiContext<>() .openApiConfiguration(config) .openApiReader(new Reader(config)) .openApiScanner(new JaxrsApplicationAndResourcePackagesAnnotationScanner().openApiConfiguration(config)) .init(); OpenAPI openApi = ctx.read(); assertNotNull(openApi); assertEquals(openApi.getPaths().keySet(), Arrays.asList("/packageA", "/packageB")); } @Test(description = "scan classes from Application when it is not set") public void shouldScanForClassesWhenApplicationIsNotSet() throws Exception { SwaggerConfiguration config = new SwaggerConfiguration() .openAPI(new OpenAPI().info(new Info().description("TEST INFO DESC"))); OpenApiContext ctx = new GenericOpenApiContext<>() .openApiConfiguration(config) .openApiReader(new Reader(config)) .openApiScanner(scanner.openApiConfiguration(config)) .init(); OpenAPI openApi = ctx.read(); assertNotNull(openApi); assertNull(openApi.getPaths()); } @Test(description = "scan classes from Application") public void shouldScanOnlyApplicationClasses() throws Exception { SwaggerConfiguration config = new SwaggerConfiguration() .openAPI(new OpenAPI().info(new Info().description("TEST INFO DESC"))); Application application = new Application() { @Override public Set> getClasses() { return Collections.singleton(ResourceInPackageA.class); } }; OpenApiContext ctx = new GenericOpenApiContext<>() .openApiConfiguration(config) .openApiReader(new Reader(config)) .openApiScanner(scanner.application(application).openApiConfiguration(config)) .init(); OpenAPI openApi = ctx.read(); assertNotNull(openApi); assertEquals(openApi.getPaths().keySet(), Arrays.asList("/packageA")); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/integration/JaxrsApplicationScannerTest.java ================================================ package io.swagger.v3.jaxrs2.integration; import java.util.Collections; import java.util.Set; import javax.ws.rs.core.Application; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.my.project.resources.ResourceInPackageA; import io.swagger.v3.oas.integration.SwaggerConfiguration; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; public class JaxrsApplicationScannerTest { private JaxrsApplicationScanner scanner; @BeforeMethod public void setUp() { scanner = new JaxrsApplicationScanner(); scanner.setApplication(new Application() { @Override public Set> getClasses() { return Collections.singleton(ResourceInPackageA.class); } }); } @Test(description = "scan classes from Application only") public void shouldScanClassesApplicationOnly() throws Exception { assertEquals(scanner.classes().size(), 1); assertTrue(scanner.classes().contains(ResourceInPackageA.class)); } @Test(description = "scan classes from the Application only, ignoring resource packages") public void shouldScanClassesFromApplicationOnlyIgnoringResourcePackages() throws Exception { SwaggerConfiguration openApiConfiguration = new SwaggerConfiguration(); openApiConfiguration.setResourcePackages(Collections.singleton("com.my.project.resources")); scanner.setConfiguration(openApiConfiguration); assertEquals(scanner.classes().size(), 1); assertTrue(scanner.classes().contains(ResourceInPackageA.class)); } @Test(description = "scan classes from Application when is not set") public void shouldScanForClassesWhenApplicationNotSet() throws Exception { scanner.application(null); assertTrue(scanner.classes().isEmpty()); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/integration/SortedOutputTest.java ================================================ package io.swagger.v3.jaxrs2.integration; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.swagger.v3.core.jackson.PathsSerializer; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.ObjectMapperProcessor; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.media.Schema; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Application; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.Map; import java.util.Set; import static org.testng.Assert.assertEquals; public class SortedOutputTest { private JaxrsApplicationAndAnnotationScanner scanner; @Path("/app") protected static class ResourceInApplication { @Operation(operationId = "test.") @GET public void getTest(@Parameter(name = "test") ArrayList tenantId) { return; } } @BeforeMethod public void setUp() { scanner = new JaxrsApplicationAndAnnotationScanner(); scanner.setApplication(new Application() { @Override public Set> getClasses() { return Collections.singleton(ResourceInApplication.class); } }); } @Test(description = "sort output test") public void sortOutputTest() throws Exception { SwaggerConfiguration openApiConfiguration = new SwaggerConfiguration() .sortOutput(true) .resourcePackages(Collections.singleton("com.my.sorted.resources")); OpenApiContext ctx = new JaxrsOpenApiContext<>() .openApiConfiguration(openApiConfiguration) .init(); OpenAPI openApi = ctx.read(); String sorted = ctx.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(openApi); openApiConfiguration = new SwaggerConfiguration() .resourcePackages(Collections.singleton("com.my.sorted.resources")); ctx = new JaxrsOpenApiContext<>() .openApiConfiguration(openApiConfiguration) .init(); String notSorted = ctx.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(openApi); assertEquals(sorted, expectedSorted); assertEquals(notSorted, expectedNotSorted); } @JsonPropertyOrder(value = {"openapi", "info", "externalDocs", "servers", "security", "tags", "paths", "components"}, alphabetic = true) public static abstract class SortedOpenAPIMixin { @JsonAnyGetter @JsonPropertyOrder(alphabetic = true) public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonSerialize(using = PathsSerializer.class) public abstract Paths getPaths(); } @JsonPropertyOrder(value = {"type", "format"}, alphabetic = true) public static abstract class SortedSchemaMixin { @JsonAnyGetter @JsonPropertyOrder(alphabetic = true) public abstract Map getExtensions(); @JsonAnySetter public abstract void addExtension(String name, Object value); @JsonIgnore public abstract boolean getExampleSetFlag(); @JsonInclude(value = JsonInclude.Include.NON_NULL, content = JsonInclude.Include.ALWAYS) public abstract Object getExample(); @JsonIgnore public abstract Map getJsonSchema(); @JsonIgnore public abstract BigDecimal getExclusiveMinimumValue(); @JsonIgnore public abstract BigDecimal getExclusiveMaximumValue(); @JsonIgnore public abstract Map getPatternProperties(); @JsonIgnore public abstract Schema getContains(); @JsonIgnore public abstract String get$id(); @JsonIgnore public abstract String get$anchor(); @JsonIgnore public abstract String get$schema(); @JsonIgnore public abstract Set getTypes(); @JsonIgnore public abstract Object getJsonSchemaImpl(); } public static class SortedProcessor implements ObjectMapperProcessor { @Override public void processOutputJsonObjectMapper(ObjectMapper mapper) { mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); mapper.addMixIn(OpenAPI.class, SortedOpenAPIMixin.class); mapper.addMixIn(Schema.class, SortedSchemaMixin.class); } @Override public void processOutputYamlObjectMapper(ObjectMapper mapper) { mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); mapper.addMixIn(OpenAPI.class, SortedOpenAPIMixin.class); mapper.addMixIn(Schema.class, SortedSchemaMixin.class); } } @Test(description = "config output test") public void configOutputTest() throws Exception { SwaggerConfiguration openApiConfiguration = new SwaggerConfiguration() .objectMapperProcessorClass(SortedProcessor.class.getName()) .resourcePackages(Collections.singleton("com.my.sorted.resources")); OpenApiContext ctx = new JaxrsOpenApiContext<>() .openApiConfiguration(openApiConfiguration) .init(); OpenAPI openApi = ctx.read(); String sorted = ctx.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(openApi); openApiConfiguration = new SwaggerConfiguration() .resourcePackages(Collections.singleton("com.my.sorted.resources")); ctx = new JaxrsOpenApiContext<>() .openApiConfiguration(openApiConfiguration) .init(); String notSorted = ctx.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(openApi); assertEquals(sorted, expectedSorted); assertEquals(notSorted, expectedNotSorted); } String expectedSorted = "openapi: 3.0.1\n" + "paths:\n" + " /sorted/pet:\n" + " get:\n" + " operationId: foo\n" + " responses:\n" + " default:\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + " description: default response\n" + "components:\n" + " schemas:\n" + " Category:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Category\n" + " Pet:\n" + " type: object\n" + " properties:\n" + " category:\n" + " $ref: \"#/components/schemas/Category\"\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " photoUrls:\n" + " type: array\n" + " items:\n" + " type: string\n" + " xml:\n" + " name: photoUrl\n" + " xml:\n" + " wrapped: true\n" + " status:\n" + " type: string\n" + " description: pet status in the store\n" + " enum:\n" + " - \"available,pending,sold\"\n" + " tags:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Tag\"\n" + " xml:\n" + " wrapped: true\n" + " xml:\n" + " name: Pet\n" + " Tag:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Tag\n"; String expectedNotSorted = "openapi: 3.0.1\n" + "paths:\n" + " /sorted/pet:\n" + " get:\n" + " operationId: foo\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/Pet\"\n" + "components:\n" + " schemas:\n" + " Category:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Category\n" + " Pet:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " category:\n" + " $ref: \"#/components/schemas/Category\"\n" + " name:\n" + " type: string\n" + " photoUrls:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " type: string\n" + " xml:\n" + " name: photoUrl\n" + " tags:\n" + " type: array\n" + " xml:\n" + " wrapped: true\n" + " items:\n" + " $ref: \"#/components/schemas/Tag\"\n" + " status:\n" + " type: string\n" + " description: pet status in the store\n" + " enum:\n" + " - \"available,pending,sold\"\n" + " xml:\n" + " name: Pet\n" + " Tag:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " name:\n" + " type: string\n" + " xml:\n" + " name: Tag\n"; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/it/OpenApiResourceIT.java ================================================ package io.swagger.v3.jaxrs2.it; import com.fasterxml.jackson.databind.SerializationFeature; import io.restassured.http.ContentType; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest; import org.testng.SkipException; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.io.IOException; import static io.restassured.RestAssured.given; import static org.testng.Assert.assertTrue; /** *

* An functional integration test that runs during maven's integration-test phase, * uses RestAssured to define REST API tests, and Jetty's Maven plugin to serve a simple * sample app just prior to the integration-test phase starting. */ public class OpenApiResourceIT extends AbstractAnnotationTest { private static final String EXPECTED_JSON = "{\n" + " \"openapi\": \"3.0.1\",\n" + " \"paths\": {\n" + " \"/cars/all\": {\n" + " \"get\": {\n" + " \"tags\": [\n" + " \"cars\"\n" + " ],\n" + " \"description\": \"Return whole car\",\n" + " \"operationId\": \"getAll\",\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"content\": {\n" + " \"application/json\": {\n" + " \"schema\": {\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"$ref\": \"#/components/schemas/Car\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"/cars/summary\": {\n" + " \"get\": {\n" + " \"tags\": [\n" + " \"cars\"\n" + " ],\n" + " \"description\": \"Return car summaries\",\n" + " \"operationId\": \"getSummaries\",\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"content\": {\n" + " \"application/json\": {\n" + " \"schema\": {\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"$ref\": \"#/components/schemas/Car_Summary\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"/cars/detail\": {\n" + " \"get\": {\n" + " \"tags\": [\n" + " \"cars\"\n" + " ],\n" + " \"description\": \"Return car detail\",\n" + " \"operationId\": \"getDetails\",\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"content\": {\n" + " \"application/json\": {\n" + " \"schema\": {\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"$ref\": \"#/components/schemas/Car_Detail\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"/cars/sale\": {\n" + " \"get\": {\n" + " \"tags\": [\n" + " \"cars\"\n" + " ],\n" + " \"operationId\": \"getSaleSummaries\",\n" + " \"responses\": {\n" + " \"default\": {\n" + " \"description\": \"default response\",\n" + " \"content\": {\n" + " \"application/json\": {\n" + " \"schema\": {\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"$ref\": \"#/components/schemas/Car_Summary-or-Sale\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"/files/upload\": {\n" + " \"post\": {\n" + " \"operationId\": \"uploadFile\",\n" + " \"requestBody\": {\n" + " \"content\": {\n" + " \"multipart/form-data\": {\n" + " \"schema\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"fileIdRenamed\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"fileRenamed\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"binary\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"responses\": {\n" + " \"default\": {\n" + " \"description\": \"default response\",\n" + " \"content\": {\n" + " \"application/json\": {\n" + " \n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"/files/attach\": {\n" + " \"put\": {\n" + " \"operationId\": \"putFile\",\n" + " \"requestBody\": {\n" + " \"content\": {\n" + " \"application/octet-stream\": {\n" + " \"schema\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"binary\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"responses\": {\n" + " \"default\": {\n" + " \"description\": \"default response\",\n" + " \"content\": {\n" + " \"application/json\": {\n" + " \n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"/users/add\": {\n" + " \"post\": {\n" + " \"operationId\": \"addUser\",\n" + " \"requestBody\": {\n" + " \"content\": {\n" + " \"application/x-www-form-urlencoded\": {\n" + " \"schema\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"gender\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"responses\": {\n" + " \"default\": {\n" + " \"description\": \"default response\",\n" + " \"content\": {\n" + " \"application/json\": {\n" + " \n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"/widgets/{widgetId}\": {\n" + " \"get\": {\n" + " \"tags\": [\n" + " \"widgets\"\n" + " ],\n" + " \"summary\": \"Find pet by ID\",\n" + " \"description\": \"Returns a pet when ID <= 10. ID > 10 or nonintegers will simulate API error conditions\",\n" + " \"operationId\": \"getWidget\",\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"widgetId\",\n" + " \"in\": \"path\",\n" + " \"required\": true,\n" + " \"schema\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " ],\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"Returns widget with matching id\",\n" + " \"content\": {\n" + " \"application/json\": {\n" + " \"schema\": {\n" + " \"$ref\": \"#/components/schemas/Widget\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"components\": {\n" + " \"schemas\": {\n" + " \"Tire_Detail\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"condition\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"brand\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"Car\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"model\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"tires\": {\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"$ref\": \"#/components/schemas/Tire\"\n" + " }\n" + " },\n" + " \"price\": {\n" + " \"type\": \"integer\",\n" + " \"format\": \"int32\"\n" + " },\n" + " \"color\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"manufacture\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"Car_Summary-or-Sale\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"model\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"price\": {\n" + " \"type\": \"integer\",\n" + " \"format\": \"int32\"\n" + " },\n" + " \"color\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"manufacture\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"Car_Detail\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"model\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"tires\": {\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"$ref\": \"#/components/schemas/Tire_Detail\"\n" + " }\n" + " },\n" + " \"color\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"manufacture\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"Widget\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"a\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"b\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"id\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"Car_Summary\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"model\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"color\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"manufacture\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"Tire\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"condition\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"brand\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; private static final String EXPECTED_YAML = "openapi: 3.0.1\n" + "paths:\n" + " /cars/all:\n" + " get:\n" + " tags:\n" + " - cars\n" + " description: Return whole car\n" + " operationId: getAll\n" + " responses:\n" + " \"200\":\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Car\"\n" + " /cars/detail:\n" + " get:\n" + " tags:\n" + " - cars\n" + " description: Return car detail\n" + " operationId: getDetails\n" + " responses:\n" + " \"200\":\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Car_Detail\"\n" + " /cars/sale:\n" + " get:\n" + " tags:\n" + " - cars\n" + " operationId: getSaleSummaries\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Car_Summary-or-Sale\"\n" + " /cars/summary:\n" + " get:\n" + " tags:\n" + " - cars\n" + " description: Return car summaries\n" + " operationId: getSummaries\n" + " responses:\n" + " \"200\":\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Car_Summary\"\n" + " /files/attach:\n" + " put:\n" + " operationId: putFile\n" + " requestBody:\n" + " content:\n" + " application/octet-stream:\n" + " schema:\n" + " type: string\n" + " format: binary\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n" + " /files/upload:\n" + " post:\n" + " operationId: uploadFile\n" + " requestBody:\n" + " content:\n" + " multipart/form-data:\n" + " schema:\n" + " type: object\n" + " properties:\n" + " fileIdRenamed:\n" + " type: string\n" + " fileRenamed:\n" + " type: string\n" + " format: binary\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n" + " /users/add:\n" + " post:\n" + " operationId: addUser\n" + " requestBody:\n" + " content:\n" + " application/x-www-form-urlencoded:\n" + " schema:\n" + " type: object\n" + " properties:\n" + " gender:\n" + " type: string\n" + " id:\n" + " type: string\n" + " name:\n" + " type: string\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " application/json: {}\n" + " /widgets/{widgetId}:\n" + " get:\n" + " tags:\n" + " - widgets\n" + " summary: Find pet by ID\n" + " description: Returns a pet when ID <= 10. ID > 10 or nonintegers will simulate\n" + " API error conditions\n" + " operationId: getWidget\n" + " parameters:\n" + " - name: widgetId\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " responses:\n" + " \"200\":\n" + " description: Returns widget with matching id\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Widget\"\n" + "components:\n" + " schemas:\n" + " Car:\n" + " type: object\n" + " properties:\n" + " color:\n" + " type: string\n" + " manufacture:\n" + " type: string\n" + " model:\n" + " type: string\n" + " price:\n" + " type: integer\n" + " format: int32\n" + " tires:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Tire\"\n" + " Car_Detail:\n" + " type: object\n" + " properties:\n" + " color:\n" + " type: string\n" + " manufacture:\n" + " type: string\n" + " model:\n" + " type: string\n" + " tires:\n" + " type: array\n" + " items:\n" + " $ref: \"#/components/schemas/Tire_Detail\"\n" + " Car_Summary:\n" + " type: object\n" + " properties:\n" + " color:\n" + " type: string\n" + " manufacture:\n" + " type: string\n" + " model:\n" + " type: string\n" + " Car_Summary-or-Sale:\n" + " type: object\n" + " properties:\n" + " color:\n" + " type: string\n" + " manufacture:\n" + " type: string\n" + " model:\n" + " type: string\n" + " price:\n" + " type: integer\n" + " format: int32\n" + " Tire:\n" + " type: object\n" + " properties:\n" + " brand:\n" + " type: string\n" + " condition:\n" + " type: string\n" + " Tire_Detail:\n" + " type: object\n" + " properties:\n" + " brand:\n" + " type: string\n" + " condition:\n" + " type: string\n" + " Widget:\n" + " type: object\n" + " properties:\n" + " a:\n" + " type: string\n" + " b:\n" + " type: string\n" + " id:\n" + " type: string\n"; private static final int jettyPort = System.getProperties().containsKey("jetty.port") ? Integer.parseInt(System.getProperty("jetty.port")): -1; @BeforeMethod public void checkJetty() { if (jettyPort == -1) { throw new SkipException("Jetty not configured"); } } @Test public void testSwaggerJson() throws Exception { final String actualBody = given() .port(jettyPort) .log().all() .when() .get("/openapi.json") .then() .log().all() .assertThat() .statusCode(200) .contentType(ContentType.JSON) .extract() .response().body().asString(); compareAsJson(formatJson(actualBody), EXPECTED_JSON); } @Test public void testSwaggerJsonUsingAcceptHeader() throws Exception { final String actualBody = given() .port(jettyPort) .log().all() .accept(ContentType.JSON) .when() .get("/openapi") .then() .log().all() .assertThat() .statusCode(200) .contentType(ContentType.JSON) .extract().response().body().asString(); compareAsJson(formatJson(actualBody), EXPECTED_JSON); } @Test public void testSwaggerYaml() throws Exception { final String actualBody = given() .port(jettyPort) .log().all() .when() .get("/openapi.yaml") .then() .log().all() .assertThat() .statusCode(200) .contentType("application/yaml") .extract().response().body().asString(); compareAsYaml(formatYaml(actualBody), EXPECTED_YAML); } @Test public void testSwaggerYamlUsingAcceptHeader() throws Exception { final String actualBody = given() .port(jettyPort) .log().all() .accept("application/yaml") .when() .get("/openapi") .then() .log().all() .assertThat() .statusCode(200) .contentType("application/yaml") .extract().response().body().asString(); compareAsYaml(formatYaml(actualBody), EXPECTED_YAML); } @Test public void testYamlOpenAPI31() throws Exception { final String actualBody = given() .port(jettyPort) .log().all() .accept("application/yaml") .when() .get("/oas/openapi31") .then() .log().all() .assertThat() .statusCode(200) .contentType("application/yaml") .extract().response().body().asString(); assertTrue(actualBody.contains("openapi: 3.1.0")); } @Test public void testServletOpenAPI31() throws Exception { final String actualBody = given() .port(jettyPort) .log().all() .when() .get("/oas/openapi.yaml") .then() .log().all() .assertThat() .statusCode(200) .contentType("application/yaml") .extract().response().body().asString(); assertTrue(actualBody.contains("openapi: 3.1.0")); } @Test public void testYamlOpenAPI31WithBootstrapServlet() throws Exception { final String actualBody = given() .port(jettyPort) .log().all() .when() .get("/bootstrap") .then() .log().all() .assertThat() .statusCode(200) .extract().response().body().asString(); assertTrue(actualBody.contains("openapi: 3.1.0")); } private String formatYaml(String source) throws IOException { return Yaml.mapper().configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) .writerWithDefaultPrettyPrinter() .writeValueAsString(Yaml.mapper().readValue(source, Object.class)); } private String formatJson(String source) throws IOException { return Json.mapper().configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) .writerWithDefaultPrettyPrinter() .writeValueAsString(Json.mapper().readValue(source, Object.class)); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/it/model/Widget.java ================================================ package io.swagger.v3.jaxrs2.it.model; public class Widget { private String a; private String b; private String id; public String getA() { return a; } public Widget setA(String a) { this.a = a; return this; } public String getB() { return b; } public Widget setB(String b) { this.b = b; return this; } public String getId() { return id; } public Widget setId(String id) { this.id = id; return this; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/it/resources/CarResource.java ================================================ package io.swagger.v3.jaxrs2.it.resources; import javax.ws.rs.Consumes; import javax.ws.rs.Path; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import java.util.Arrays; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; @Path("/cars") @Tag(name = "cars") @Produces("application/json") @Consumes("application/json") public class CarResource { private static class View { interface Summary { } interface Detail extends View.Summary { } interface Sale { } } private static class Car { @JsonView(View.Summary.class) @JsonProperty("manufacture") private String made = "Honda"; @JsonView({View.Summary.class, View.Detail.class}) private String model = "Accord Hybrid"; @JsonView({View.Detail.class}) @JsonProperty private List tires = Arrays.asList(new Tire()); @JsonView({View.Sale.class}) @JsonProperty private int price = 40000; // always in private String color = "White"; public String getColor() { return color; } } private static class Tire { @JsonView(View.Summary.class) @JsonProperty("brand") private String made = "Michelin"; @JsonView(View.Detail.class) @JsonProperty private String condition = "new"; } @GET @Path("/summary") @JsonView({View.Summary.class}) @Operation(description = "Return car summaries", responses = @ApiResponse(responseCode = "200", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Car.class))))) public Response getSummaries() { return Response.ok(Arrays.asList(new Car())).build(); } @GET @Path("/detail") @JsonView({View.Detail.class}) @Operation(description = "Return car detail", responses = @ApiResponse(responseCode = "200", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Car.class))))) public List getDetails() { return Arrays.asList(new Car()); } @GET @Path("/sale") @JsonView({View.Summary.class, View.Sale.class}) public List getSaleSummaries() { return Arrays.asList(new Car()); } @GET @Path("/all") @Operation(description = "Return whole car", responses = @ApiResponse(responseCode = "200", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Car.class))))) public List getAll() { return Arrays.asList(new Car()); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/it/resources/MultiPartFileResource.java ================================================ package io.swagger.v3.jaxrs2.it.resources; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import org.glassfish.jersey.media.multipart.FormDataParam; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.io.InputStream; @Path("/files") @Produces("application/json") public class MultiPartFileResource { @POST @Path("/upload") @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadFile(@FormDataParam("fileIdRenamed") final String fileId, @Parameter(schema = @Schema(type = "string", format = "binary")) @FormDataParam("fileRenamed") final InputStream file) { return Response.status(200).entity("File " + fileId + " has been uploaded").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/it/resources/OctetStreamResource.java ================================================ package io.swagger.v3.jaxrs2.it.resources; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.Consumes; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.io.InputStream; @Path("/files") @Produces("application/json") public class OctetStreamResource { @PUT @Path("/attach") @Consumes(MediaType.APPLICATION_OCTET_STREAM) public Response putFile(@RequestBody(content = @Content(mediaType = MediaType.APPLICATION_OCTET_STREAM, schema = @Schema(type = "string", format = "binary"))) InputStream fileInputStream) { return Response.status(200).entity("File has been attached").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/it/resources/UrlEncodedResource.java ================================================ package io.swagger.v3.jaxrs2.it.resources; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @Path("/users") @Produces("application/json") public class UrlEncodedResource { @POST @Path("/add") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response addUser(@FormParam("id") final String id, @FormParam("name") final String name, @FormParam("gender") final String gender) { return Response.status(200).entity("Adding user " + id + " to the system.").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/it/resources/WidgetResource.java ================================================ package io.swagger.v3.jaxrs2.it.resources; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import io.swagger.v3.jaxrs2.it.model.Widget; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.core.Response; @Path("/widgets") @Tag(name="widgets") @Produces("application/json") @Consumes("application/json") public class WidgetResource { @Path("/{widgetId}") @GET @Operation(summary = "Find pet by ID", description = "Returns a pet when ID <= 10. ID > 10 or nonintegers will simulate API error conditions", responses = @ApiResponse( content = @Content(schema = @Schema(implementation = Widget.class)), description = "Returns widget with matching id", responseCode = "200" ) ) public Response getWidget(@PathParam("widgetId") String widgetId) { return Response.ok(new Widget().setA("foo").setB("bar")).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/matchers/SerializationMatchers.java ================================================ package io.swagger.v3.jaxrs2.matchers; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.NumericNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Comparator; import static org.testng.Assert.assertEquals; public class SerializationMatchers { private static final Logger LOGGER = LoggerFactory.getLogger(SerializationMatchers.class); public static void assertEqualsToYaml(Object objectToSerialize, String yamlStr) { apply(objectToSerialize, yamlStr, Yaml.mapper(), false); } public static void assertEqualsToYamlExact(Object objectToSerialize, String yamlStr) { apply(objectToSerialize, yamlStr, Yaml.mapper(), true); } public static void assertEqualsToJson(Object objectToSerialize, String jsonStr) { apply(objectToSerialize, jsonStr, Json.mapper(), false); } public static void assertEqualsToYaml31(Object objectToSerialize, String yamlStr) { apply31(objectToSerialize, yamlStr, Yaml31.mapper()); } public static void assertEqualsToJson31(Object objectToSerialize, String jsonStr) { apply31(objectToSerialize, jsonStr, Json31.mapper()); } private static void apply(Object objectToSerialize, String str, ObjectMapper mapper, boolean exactMatch) { final ObjectNode lhs = mapper.convertValue(objectToSerialize, ObjectNode.class); ObjectNode rhs = null; try { rhs = mapper.readValue(str, ObjectNode.class); } catch (IOException e) { LOGGER.error("Failed to read value", e); } if (exactMatch || !lhs.equals(new ObjectNodeComparator(), rhs)) { assertEquals(Yaml.pretty(lhs), Yaml.pretty(rhs)); //fail(String.format("Serialized object:\n%s\ndoes not equal to expected serialized string:\n%s", lhs, rhs)); } } private static void apply31(Object objectToSerialize, String str, ObjectMapper mapper) { final ObjectNode lhs = mapper.convertValue(objectToSerialize, ObjectNode.class); ObjectNode rhs = null; try { rhs = mapper.readValue(str, ObjectNode.class); } catch (IOException e) { LOGGER.error("Failed to read value", e); } if (!lhs.equals(new ObjectNodeComparator(), rhs)) { assertEquals(Yaml31.pretty(lhs), Yaml31.pretty(rhs)); } } static final class ObjectNodeComparator implements Comparator { @Override public int compare(JsonNode o1, JsonNode o2) { if (o1.equals(o2)) { return 0; } if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)) { double d1 = ((NumericNode) o1).asDouble(); double d2 = ((NumericNode) o2).asDouble(); return Double.compare(d1, d2); } int comp = o1.asText().compareTo(o2.asText()); if (comp == 0) { return Integer.compare(o1.hashCode(), o2.hashCode()); } return comp; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/EmptyPetResource.java ================================================ package io.swagger.v3.jaxrs2.petstore; /** * An Empty PetResource Class */ public class EmptyPetResource { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/PetResource.java ================================================ package io.swagger.v3.jaxrs2.petstore; import io.swagger.v3.jaxrs2.resources.QueryResultBean; import io.swagger.v3.jaxrs2.resources.data.PetData; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; @Consumes("application/json") @Path("/pet") @Produces({"application/json", "application/xml"}) public class PetResource { static PetData petData = new PetData(); @GET @Path("/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched"/*, _enum = "range[1,10]"*/, required = true) @PathParam("petId") final Long petId) throws NotFoundException { Pet pet = petData.getPetById(petId); if (null != pet) { return Response.ok().entity(pet).build(); } else { throw new NotFoundException(404, "Pet not found"); } } @POST @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPet( @Parameter(description = "Pet object that needs to be added to the store", required = true) final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodynoannotation") @Consumes({"application/json", "application/xml"}) @Produces({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store no annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetNoAnnotation(final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyid") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer with generic parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByInteger( @Parameter(description = "Pet object that needs to be added to the store", required = true) final int petId) { return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyidnoannotation") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer without parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByIntegerNoAnnotation(final int petId) { return Response.ok().entity("SUCCESS").build(); } @PUT @Operation(summary = "Update an existing pet", responses = { @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found"), @ApiResponse(responseCode = "405", description = "Validation exception")}) public Response updatePet( @Parameter(description = "Pet object that needs to be added to the store", required = true) final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @GET @Path("/findByStatus") @Produces("application/xml") @Operation(summary = "Finds Pets by status", description = "Multiple status values can be provided with comma separated strings", responses = { @ApiResponse( content = @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))), @ApiResponse( responseCode = "400", description = "Invalid status value" )} ) public Response findPetsByStatus( @Parameter(description = "Status values that need to be considered for filter", required = true) @QueryParam("status") final String status, @BeanParam final QueryResultBean qr ) { return Response.ok(petData.findPetByStatus(status)).build(); } @GET @Path("/findByTags") @Produces("application/json") @Operation(summary = "Finds Pets by tags", description = "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", responses = { @ApiResponse(description = "Pets matching criteria", content = @Content(schema = @Schema(implementation = Pet.class)) ), @ApiResponse(description = "Invalid tag value", responseCode = "400") }) @Deprecated public Response findPetsByTags( @Parameter(description = "Tags to filter by", required = true) @QueryParam("tags") final String tags) { return Response.ok(petData.findPetByTags(tags)).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/WebHookResource.java ================================================ package io.swagger.v3.jaxrs2.petstore; import io.swagger.v3.jaxrs2.petstore.parameter.Parameters31Resource; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.Webhook; import io.swagger.v3.oas.annotations.Webhooks; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @Webhooks({ @Webhook( name = "webhook1", operation = @Operation(operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema( $id = "http://yourdomain.com/schemas/myschema.json", $comment = "schema $comment", type = "string" ), style = ParameterStyle.SIMPLE), @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema( types = {"string", "number"}, exclusiveMaximumValue = 100, $schema = "parameter $schema", $anchor = "parameter $anchor", _if = Parameters31Resource.SubscriptionResponse.class, _else = Parameters31Resource.SubscriptionResponse.class, then = Parameters31Resource.SubscriptionResponse.class ) ) } ) ), @Webhook( name = "webhook2", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( $id = "http://yourdomain.com/schemas/myschema.json", $comment = "random comment", types = { "integer", "number" }, dependentSchemas = { @StringToClassMapItem( key = "pet", value = Object.class ) }, patternProperties = { @StringToClassMapItem( key = "user", value = Object.class ) }, format = "int32" ) ) ) ) ) }) public class WebHookResource { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/callback/ComplexCallback31Resource.java ================================================ package io.swagger.v3.jaxrs2.petstore.callback; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class ComplexCallback31Resource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( $id = "http://yourdomain.com/schemas/myschema.json", $comment = "random comment", types = { "integer", "number" }, dependentSchemas = { @StringToClassMapItem( key = "pet", value = Object.class ) }, patternProperties = { @StringToClassMapItem( key = "user", value = Object.class ) }, format = "int32")))), callbackUrlExpression = "http://www.url.com"), @Callback( name = "testCallback2", operation = @Operation( operationId = "getAnSpecificReviews", summary = "get a review", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( implementation = User.class)))), callbackUrlExpression = "http://www.url2.com") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/complexcallback") public String simpleGet(@Parameter(description = "idParam", schema = @Schema(implementation = User.class)) @QueryParam("id") final String id) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/callback/ComplexCallbackResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.callback; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class ComplexCallbackResource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com"), @Callback( name = "testCallback2", operation = @Operation( operationId = "getAnSpecificReviews", summary = "get a review", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( implementation = User.class)))), callbackUrlExpression = "http://www.url2.com") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/complexcallback") public String simpleGet(@Parameter(description = "idParam", schema = @Schema(implementation = User.class)) @QueryParam("id") final String id) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/callback/MultipleCallbacksTestWithOperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class MultipleCallbacksTestWithOperationResource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com"), @Callback(name = "testCallback2", operation = @Operation(), callbackUrlExpression = "http://$request.query.url") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/multiplecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/callback/RepeatableCallbackResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class RepeatableCallbackResource { @Callback(name = "testCallback", operation = @Operation(), callbackUrlExpression = "http://$requests.query.url") @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com") @Callback(name = "testCallback2", operation = @Operation(), callbackUrlExpression = "http://$request.query.url") @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/repeatablecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/callback/SimpleCallbackWithOperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class SimpleCallbackWithOperationResource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/simplecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/example/ExamplesResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.example; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.POST; import javax.ws.rs.Path; /** * Examples Resource Scenario */ public class ExamplesResource { @Path("/example") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(name = "Schema", description = "Schema", example = "Subscription example"), style = ParameterStyle.SIMPLE, example = "example", examples = { @ExampleObject(name = "subscriptionId_1", value = "12345", summary = "Subscription number 12345", externalValue = "Subscription external value 1"), @ExampleObject(name = "subscriptionId_2", value = "54321", summary = "Subscription number 54321", externalValue = "Subscription external value 2") }) }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example" ), examples = { @ExampleObject(name = "Default Response", value = "SubscriptionResponse", summary = "Subscription Response Example", externalValue = "Subscription Response value 1") } )) }) public SubscriptionResponse subscribe(@RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example"), examples = { @ExampleObject(name = "Default Request", value = "SubscriptionRequest", summary = "Subscription Request Example", externalValue = "Subscription Request Value") })) User user) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/example/SubscriptionResponse.java ================================================ package io.swagger.v3.jaxrs2.petstore.example; public class SubscriptionResponse { public String subscriptionId; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/link/LinksAndContent31Resource.java ================================================ package io.swagger.v3.jaxrs2.petstore.link; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.DependentSchema; import io.swagger.v3.oas.annotations.media.DependentSchemas; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with Links */ public class LinksAndContent31Resource { @Path("/links") @Operation(operationId = "getUserWithAddress", responses = { @ApiResponse(description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( types = { "object" } ), dependentSchemas = { @DependentSchema( name = "value", schema = @Schema( types = { "string", "number" } ) ) } ), links = { @Link( name = "address", operationId = "getAddress", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")), @Link( name = "user", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId"), extensions = @Extension( name = "x-one", properties = { @ExtensionProperty( name = "x-sample-extension", value = "true" ) } ) ) })} ) @GET public String getUser(@QueryParam("userId")final String userId) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/link/LinksResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.link; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with Links */ public class LinksResource { @Path("/links") @Operation(operationId = "getUserWithAddress", responses = { @ApiResponse(description = "test description", content = @Content(mediaType = "*/*", schema = @Schema(ref = "#/components/schemas/User")), links = { @Link( name = "address", operationId = "getAddress", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")), @Link( name = "user", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) })} ) @GET public String getUser(@QueryParam("userId")final String userId) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/openapidefintion/OpenAPI31DefinitionResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.openapidefintion; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.info.Contact; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.servers.ServerVariable; import io.swagger.v3.oas.annotations.tags.Tag; /** * OpenAPIDefinition Example */ @OpenAPIDefinition( info = @Info( title = "Pet Resource Example", version = "2.0", description = "API Definition", summary = "API Summary", termsOfService = "Terms of service", license = @License(name = "Apache 2.0", url = "http://foo.bar", identifier = "Apache"), contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com") ) ) public class OpenAPI31DefinitionResource { public void foo() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/openapidefintion/OpenAPIDefinitionResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.openapidefintion; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.info.Contact; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.servers.ServerVariable; import io.swagger.v3.oas.annotations.tags.Tag; /** * OpenAPIDefinition Example */ @OpenAPIDefinition( info = @Info( title = "Pet Resource Example", version = "2.0", description = "API Definition", termsOfService = "Terms of service", license = @License(name = "Apache 2.0", url = "http://foo.bar"), contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com") ), tags = { @Tag(name = "Tag 1", description = "desc 1", externalDocs = @ExternalDocumentation(description = "docs desc")), @Tag(name = "Tag 2", description = "desc 2", externalDocs = @ExternalDocumentation(description = "docs desc 2")), @Tag(name = "Tag 3") }, externalDocs = @ExternalDocumentation(description = "definition docs desc"), security = { @SecurityRequirement(name = "req 1", scopes = {"a", "b"}), @SecurityRequirement(name = "req 2", scopes = {"b", "c"}) }, servers = { @Server( description = "server 1", url = "http://foo", variables = { @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}), @ServerVariable(name = "var2", description = "var 2", defaultValue = "1", allowableValues = {"1", "2"}) }) } ) public class OpenAPIDefinitionResource { public void foo() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/AnnotatedSameNameOperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Default Operation without Annotation */ public class AnnotatedSameNameOperationResource { @Path("/sameOperationName") @GET @Operation(description = "Same Operation Name") public String getUser() { return new String(); } @Path("//sameOperationName") @DELETE @Operation(description = "Same Operation Name Duplicated") public String getUser(final String id) { return new String(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/ExternalDocumentationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; /** * Resource with Operations Examples */ public class ExternalDocumentationResource { @GET @Path("/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions", operationId = "petId", externalDocs = @ExternalDocumentation(description = "External in Operation", url = "http://url.me")) @ExternalDocumentation(description = "External Annotation Documentation", url = "http://url.me") public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched", required = true) @PathParam("petId") Long petId) throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/FullyAnnotatedOperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; /** * Resource with Operations Examples */ public class FullyAnnotatedOperationResource { @GET @Path("/fullyannotatedoperation/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions", operationId = "petId", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched", required = true) @PathParam("petId")final Long petId) throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/HiddenOperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Hidden Operation */ public class HiddenOperationResource { @Path("/hiddenbyflag") @GET @Operation(operationId = "Pets", description = "Pets Example", hidden = true) public Pet getPet() { return new Pet(); } @Path("/hiddenbyannotation") @GET @Operation(operationId = "Users", description = "Users Example") @Hidden public User getUser() { return new User(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/InterfaceResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; /** * Interface resource */ public interface InterfaceResource { @GET @Path("/interfaceoperation/{petId}") @Operation(summary = "Find pet by ID Operation in Parent", description = "Returns a pet in Parent" ) Response getPetById(@Parameter(description = "ID of pet that needs to be fetched", required = true) @PathParam("petId")final Long petId); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/NotAnnotatedSameNameOperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Default Operation without Annotation */ public class NotAnnotatedSameNameOperationResource { @Path("/notannotatedoperation") @GET public String getUser() { return new String(); } @Path("/notannotatedoperationduplicated") @GET public String getUser(final String id) { return new String(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/OperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.NotFoundException; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; /** * Resource with Complete Operations Examples */ public class OperationResource implements InterfaceResource { @Override @Operation(summary = "Find pet by ID Operation in SubResource", description = "Returns a pet in SubResource" ) public Response getPetById(final Long petId) { return Response.ok().entity(new Pet()).build(); } @GET @Path("/operationsresource") @Operation(summary = "Find pet by ID", description = "combinatedfullyannotatedoperation/{petId}", operationId = "petId", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched", required = true) @QueryParam("petId") final Long petId, final String message) throws NotFoundException { return Response.ok().entity(new Pet()).build(); } @Path("/operationsresource") @POST public String getUser(final String id) { return new String(); } @Path("/operationsresource") @PUT @Operation(operationId = "combinated sameOperationName", description = "combinatedsameOperationName") public String getPerson() { return new String(); } @Path("/operationsresource") @HEAD @Operation(operationId = "combinatedsameOperationNameDuplicated", description = "combinatedsameOperationNameDuplicated") public String getPerson(final String id) { return new String(); } @Path("/operationsresource2") @GET public String getUser() { return new String(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/OperationWithoutAnnotationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Default Operation without Annotation */ public class OperationWithoutAnnotationResource { @Path("/operationwithouannotation") @GET public String getUser() { return new String(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/ServerOperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.servers.Server; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Hidden Operation */ @OpenAPIDefinition( servers = { @Server(description = "server 1", url = "http://foo") } ) public class ServerOperationResource { @Path("/serversoperation") @GET @Operation(operationId = "Pets", description = "Pets Example", servers = { @Server(description = "server 2", url = "http://foo2") } ) public Pet getPet() { return new Pet(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/operation/SubResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.operation; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.core.Response; /** * SubResource */ public class SubResource implements InterfaceResource { @Override @Operation(summary = "Find pet by ID Operation in SubResource", description = "Returns a pet in SubResource" ) public Response getPetById(final Long petId) { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/ArraySchemaResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; public class ArraySchemaResource { @Path("/arrayschema") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) ), }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersResource.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersResource.SubscriptionResponse subscribe() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/ComplexParameterResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a multiple annotated. */ public class ComplexParameterResource { @Parameter(description = "Phone definied in Field") private String phone; public ComplexParameterResource(@Parameter(description = "phone Param", name = "phone") final String phone) { this.phone = phone; } @GET @Path("/complexparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam") @QueryParam("id") final String id, final String name, @QueryParam("lastName") final String lastName, @Parameter(description = "address", schema = @Schema(implementation = User.class)) @QueryParam("address") final String address) { return new User(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/ComplexParameterWithOperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a multiple annotated. */ public class ComplexParameterWithOperationResource { @Parameter(description = "Phone definied in Field") private String phone; public ComplexParameterWithOperationResource(@Parameter(description = "phone Param", name = "phone") final String phone) { this.phone = phone; } @GET @Path("/complexparameter") @Operation(operationId = "create User", parameters = { @Parameter(description = "Phone", name = "phone", in = ParameterIn.PATH) }) public User findUser(@Parameter(description = "idParam") @QueryParam("id") final String id, final String name, @QueryParam("lastName") final String lastName, @Parameter(description = "address", schema = @Schema(implementation = User.class)) @QueryParam("address") final String address) { return new User(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/MultipleNotAnnotatedParameter.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.POST; import javax.ws.rs.Path; /** * Class with a multiple not annotated parameter. */ public class MultipleNotAnnotatedParameter { @POST @Path("/multiplenoannotatedparameter") @Operation(operationId = "create User") public void createUser(final String id, final String name) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/OpenAPIJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs and open api annotation. */ public class OpenAPIJaxRSAnnotatedParameter { @GET @Path("/openapijaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam") @QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/OpenAPIWithContentJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs and open api annotation. */ public class OpenAPIWithContentJaxRSAnnotatedParameter { @GET @Path("/openapiwithcontentjaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam", content = @Content(schema = @Schema(description = "Id Schema Definition", required = true, name = "id"))) @QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/OpenAPIWithImplementationJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs and open api annotation. */ public class OpenAPIWithImplementationJaxRSAnnotatedParameter { @GET @Path("/openapiwithimplementationjaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam", schema = @Schema(implementation = User.class)) @QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/Parameters31Resource.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Resource with some Parameters examples */ public class Parameters31Resource { @Path("/parameters") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema( $id = "http://yourdomain.com/schemas/myschema.json", $comment = "schema $comment", type = "string" ), style = ParameterStyle.SIMPLE), @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema( types = { "string", "number" }, exclusiveMaximumValue = 100, $schema = "parameter $schema", $anchor = "parameter $anchor", _if = Parameters31Resource.SubscriptionResponse.class, _else = Parameters31Resource.SubscriptionResponse.class, then = Parameters31Resource.SubscriptionResponse.class )), @Parameter(in = ParameterIn.QUERY, name = "explodeAvoiding", required = true, explode = Explode.TRUE, schema = @Schema( type = "int", format = "id", exclusiveMaximumValue = 1000, exclusiveMinimumValue = 10, description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY )), @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = Parameters31Resource.SubscriptionResponse.class), uniqueItems = true ) , schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY), content = @Content(schema = @Schema(type = "number", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY)) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation", required = true, explode = Explode.TRUE, array = @ArraySchema( maxItems = 10, minItems = 1, maxContains = 50, minContains = 1, contains = @Schema(implementation = Parameters31Resource.SubscriptionResponse.class), unevaluatedItems = @Schema(implementation = Parameters31Resource.SubscriptionResponse.class), schema = @Schema(implementation = Parameters31Resource.SubscriptionResponse.class), uniqueItems = true ) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation2", required = true, explode = Explode.TRUE, schema = @Schema(implementation = Parameters31Resource.SubscriptionResponse.class)) }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( $id = "http://yourdomain.com/schemas/myschema.json", dependentSchemas = { @StringToClassMapItem( key = "pet", value = Pet.class ) }, patternProperties = { @StringToClassMapItem( key = "user", value = User.class ) }, properties = { @StringToClassMapItem( key = "extraObject", value = Object.class ) } ) )) }) @Consumes({"application/json", "application/xml"}) public Parameters31Resource.SubscriptionResponse subscribe(@Parameter(description = "idParam") @QueryParam("id") final String id) { return null; } public static class SubscriptionResponse { public String subscriptionId; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/ParametersResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Resource with some Parameters examples */ public class ParametersResource { @Path("/parameters") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(implementation = RepeatableParametersResource.SubscriptionResponse.class), style = ParameterStyle.SIMPLE), @Parameter(in = ParameterIn.QUERY, name = "formId", required = true, example = "Example"), @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)), @Parameter(in = ParameterIn.QUERY, name = "explodeTrue", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)), @Parameter(in = ParameterIn.QUERY, name = "explodeAvoiding", required = true, explode = Explode.TRUE, schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY )), @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) , schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY), content = @Content(schema = @Schema(type = "number", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY)) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation2", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersResource.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersResource.SubscriptionResponse subscribe(@Parameter(description = "idParam") @QueryParam("id") final String id) { return null; } static class SubscriptionResponse { public String subscriptionId; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/RepeatableParametersResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; public class RepeatableParametersResource { @Path("/repeatableparameter") @POST @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), style = ParameterStyle.SIMPLE) @Parameter(in = ParameterIn.QUERY, name = "formId", required = true, example = "Example") @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) @Parameter(in = ParameterIn.QUERY, name = "explodeTrue", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) @Parameter(in = ParameterIn.QUERY, name = "explodeAvoiding", required = true, explode = Explode.TRUE, schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY )) @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) , schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY), content = @Content(schema = @Schema(type = "number", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY)) ) @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) ) @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation2", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersResource.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersResource.SubscriptionResponse subscribe() { return null; } static class SubscriptionResponse { public String subscriptionId; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/SingleJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs. */ public class SingleJaxRSAnnotatedParameter { @GET @Path("/singlejaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/parameter/SingleNotAnnotatedParameter.java ================================================ package io.swagger.v3.jaxrs2.petstore.parameter; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Class with a single not annotated parameter. */ public class SingleNotAnnotatedParameter { @GET @Path("/singlenoannotatedparameter") @Operation(operationId = "create User") public User findUser(final String id) { return new User(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/requestbody/RequestBody31Resource.java ================================================ package io.swagger.v3.jaxrs2.petstore.requestbody; import io.swagger.v3.jaxrs2.petstore.parameter.Parameters31Resource; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; /** * Resource with RequestBody examples */ public class RequestBody31Resource { @GET @Path("/methodWithRequestBodyWithoutContentWithoutImplementation") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyWithoutContentWithoutImplementation( @RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema(name = "User", description = "User description", example = "User Description", required = true, types = { "string", "number", "object" }, exclusiveMaximumValue = 100, exclusiveMinimumValue = 1, $schema = "parameter $schema", $anchor = "parameter $anchor", _if = Object.class, _else = Object.class, then = Object.class, unevaluatedProperties = Object.class ))) final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithRequestBodyAndTwoParameters") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyAndTwoParameters( @RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema(implementation = User.class))) final User user, @QueryParam("name") final String name, @QueryParam("code") final String code) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/requestbody/RequestBodyMethodPriorityResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.requestbody; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with RequestBody inside Operation and another in Method */ public class RequestBodyMethodPriorityResource { @POST @Path("/requestbodymethodpriority") @Operation(summary = "Create user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "Inside Operation")) @RequestBody(description = "Created user object on Method", required = true, content = @Content( schema = @Schema(implementation = User.class))) public Response methodWithRequestBodyAndTwoParameters(final User user) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/requestbody/RequestBodyParameterPriorityResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.requestbody; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with RequestBody inside Operation and another in Method */ public class RequestBodyParameterPriorityResource { @POST @Path("/requestbodyparameterpriority") @Operation(summary = "Create user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "Inside Operation")) @RequestBody(description = "On method") public Response methodWithRequestBodyAndTwoParameters( @RequestBody(description = "Created user object inside Parameter", required = true, content = @Content( schema = @Schema(implementation = User.class)))final User user) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/requestbody/RequestBodyResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.requestbody; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; /** * Resource with RequestBody examples */ public class RequestBodyResource { @GET @Path("/methodWithRequestBodyWithoutContent") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyWithoutContent( @RequestBody(description = "Created user object", required = true) final User user) { return Response.ok().entity("").build(); } @GET @Path("/methodWithRequestBodyWithoutContentWithoutImplementation") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyWithoutContentWithoutImplementation( @RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema(name = "User", description = "User description", example = "User Description", required = true))) final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithRequestBodyAndTwoParameters") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyAndTwoParameters( @RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema(implementation = User.class))) final User user, @QueryParam("name") final String name, @QueryParam("code") final String code) { return Response.ok().entity("").build(); } @PUT @Path("/methodWithRequestBodyWithoutAnnotation") @Operation(summary = "Modify user", description = "Modifying user.") public Response methodWithRequestBodyWithoutAnnotation( final User user) { return Response.ok().entity("").build(); } @DELETE @Path("/methodWithoutRequestBodyAndTwoParameters") @Operation(summary = "Delete user", description = "This can only be done by the logged in user.") public Response methodWithoutRequestBodyAndTwoParameters( @QueryParam("name") final String name, @QueryParam("code") final String code) { return Response.ok().entity("").build(); } @PUT @Path("/methodWithRequestBodyWithoutAnnotationAndTwoConsumes") @Operation(summary = "Modify pet", description = "Modifying pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithRequestBodyWithoutAnnotationAndTwoConsumes( final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes") @Operation(summary = "Create pet", description = "Creating pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes( final Pet pet, final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithTwoRequestBodyWithAnnotationAndTwoConsumes") @Operation(summary = "Create pet", description = "Creating pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithTwoRequestBodyWithAnnotationAndTwoConsumes( final @RequestBody(description = "Request Body Pet") Pet pet, @RequestBody(description = "Request Body User") final User user) { return Response.ok().entity("").build(); } @DELETE @Path("/methodWithOneSimpleRequestBody") @Operation(summary = "Delete pet", description = "Deleting pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithOneSimpleRequestBody(final int id) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/responses/ComplexResponseResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.responses; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource with some responses */ public class ComplexResponseResource { @GET @Path("/complexresponse") @Operation(summary = "Find pets", description = "Returns the Pets", responses = { @ApiResponse(description = "Response inside Operation", responseCode = "200", content = @Content(schema = @Schema(implementation = Pet.class))), @ApiResponse(description = "Default Pet", content = @Content(schema = @Schema(name = "Default Pet", description = "Default Pet", required = true, example = "New Pet"))) }) @ApiResponse(responseCode = "404", description = "Couldn't find pet") public Pet getPets() throws NotFoundException { return new Pet(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/responses/ImplementationResponseResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource with a Response at Method Level */ public class ImplementationResponseResource { @GET @Path("/implementationresponse") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output object", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = { @Content( mediaType = "application/json", schema = @Schema( implementation = ImplementationResponseResource.SampleResponseSchema.class) ), @Content( mediaType = "application/json", schema = @Schema( implementation = ImplementationResponseResource.SecondSampleResponseSchema.class) ) } ), @ApiResponse( responseCode = "400", description = "boo", content = @Content( mediaType = "*/*", schema = @Schema(implementation = ImplementationResponseResource.GenericError.class) ) ) } ) public void getResponses() { } static class SampleResponseSchema { @Schema(description = "the user id") private String id; } static class SecondSampleResponseSchema { @Schema(description = "the user id") private String id; } static class GenericError { private int code; private String message; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/responses/MethodArrayResponseResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.responses; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.List; /** * Resource with an Array Response at Method Level */ public class MethodArrayResponseResource { @GET @Path("/arrayresponseinmethod") @ApiResponse(content = @Content( array = @ArraySchema( arraySchema = @io.swagger.v3.oas.annotations.media.Schema(description = "Array description"), schema = @io.swagger.v3.oas.annotations.media.Schema( description = "Item description", implementation = PetInfo.class )))) public List arrayResponseWithTypeImplementation() { return null; } public class PetInfo { String name; public String getName() { return ""; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/responses/MethodResponseResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.responses; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with a Response at Method Level */ public class MethodResponseResource { @GET @Path("/responseinmethod") @Operation(summary = "Find pets", description = "Returns the Pets") @ApiResponse(responseCode = "200", description = "Status OK") public Response getPets() throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/responses/NoImplementationResponseResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Resource with a Response at Method Level */ public class NoImplementationResponseResource { @Path("/noimplementationresponseresource") @Operation(operationId = "getUser", responses = { @ApiResponse(description = "test description", responseCode = "400", links = { @Link( name = "user", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) }), @ApiResponse(description = "200 description", responseCode = "200", links = { @Link( name = "pet", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) }) } ) @GET public NoImplementationResponseResource.User getUser(@QueryParam("userId") final String userId) { return null; } static class User { private String id; private String username; public String getId() { return id; } public void setId(final String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(final String username) { this.username = username; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/responses/NoResponseResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.responses; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource with a Response at Method Level */ public class NoResponseResource { @GET @Path("/noresponse") @Operation(summary = "Find pets", description = "Returns the Pets") public User getPets() throws NotFoundException { return new User(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/responses/OperationResponseResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.responses; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with the response in the Operation Annotation */ public class OperationResponseResource { @GET @Path("/responseinoperation") @Operation(summary = "Find Users", description = "Returns the Users", responses = {@ApiResponse(responseCode = "200", description = "Status OK")}) public Response getUsers() throws NotFoundException { return Response.ok().entity(new User()).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/responses/PriorityResponseResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.responses; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with a Response at Method Level and Operation Level. */ public class PriorityResponseResource { @GET @Path("/priorityresponses") @Operation(summary = "Find pets", description = "Returns the Pets", responses = {@ApiResponse(responseCode = "200", description = "Inside Operation Response")}) @ApiResponse(responseCode = "200", description = "Inside Method Operation") public Response getPets() throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/security/SecurityResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.security; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.security.OAuthFlow; import io.swagger.v3.oas.annotations.security.OAuthFlows; import io.swagger.v3.oas.annotations.security.OAuthScope; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityScheme; import javax.ws.rs.GET; import javax.ws.rs.PATCH; import javax.ws.rs.PUT; import javax.ws.rs.Path; @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, description = "myOauthSecurity Description", flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "http://x.com", scopes = @OAuthScope( name = "write:pets", description = "modify pets in your account")) ) ) @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) @SecurityRequirement(name = "myOauth2Security", scopes = {"write:pets"} ) @Path("/security") public class SecurityResource { @GET @Operation(operationId = "Operation Id", description = "description") @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) public void getSecurity() { } @PATCH @Operation(operationId = "Operation Id 2", description = "description 2") @SecurityRequirement(name = "security_key2", scopes = {"write:pets", "read:pets"} ) public void getSecurity2() { } @PUT @Operation(operationId = "Operation Id 3", description = "description 3", security = @SecurityRequirement(name = "security_key3", scopes = {"write:pets", "read:pets"} )) public void setSecurity(String security) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/tags/CompleteTagResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @OpenAPIDefinition(tags = { @Tag(name = "Definition First Tag"), @Tag(name = "Definition Second Tag full", description = "desc definition") }) @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Fifth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Sixth Tag") public class CompleteTagResource { @GET @Path("/completetags") @Operation(tags = {"Example Tag", "Second Tag"}) @Tag(name = "Third Tag") @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc", externalDocs = @ExternalDocumentation(description = "docs desc")) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/tags/TagClassResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.tags.Tag; /** * Class with Tag Annotations at Class level */ @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Fifth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Sixth Tag") public class TagClassResource { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/tags/TagMethodResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; public class TagMethodResource { @GET @Path("/tagsinmethod") @Tag(name = "Third Tag") @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc", externalDocs = @ExternalDocumentation(description = "docs desc")) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/tags/TagOpenAPIDefinitionResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.tags; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.tags.Tag; /** * Tag in the OpenAPIDefinition annotation */ @OpenAPIDefinition(tags = { @Tag(name = "Definition First Tag"), @Tag(name = "Definition Second Tag full", description = "desc definition") }) public class TagOpenAPIDefinitionResource { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore/tags/TagOperationResource.java ================================================ package io.swagger.v3.jaxrs2.petstore.tags; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with a Tag at Operation Level */ public class TagOperationResource { @GET @Path("/tagoperation") @Operation(tags = {"Example Tag", "Second Tag"}) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore31/Category.java ================================================ package io.swagger.v3.jaxrs2.petstore31; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Category") public class Category { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } public Category() { } public Category(String name) { this.name = name; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore31/Pet.java ================================================ package io.swagger.v3.jaxrs2.petstore31; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.util.ArrayList; import java.util.List; @XmlRootElement(name = "Pet") public class Pet { private long id; private Category category; private String name; private List photoUrls = new ArrayList(); private List tags = new ArrayList(); private String status; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "category") public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElementWrapper(name = "photoUrls") @XmlElement(name = "photoUrl") public List getPhotoUrls() { return photoUrls; } public void setPhotoUrls(List photoUrls) { this.photoUrls = photoUrls; } @XmlElementWrapper(name = "tags") @XmlElement(name = "tag") public List getTags() { return tags; } public void setTags(List tags) { this.tags = tags; } @XmlElement(name = "status") @Schema( description = "pet status in the store", allowableValues = "available,pending,sold", $id = "idtest", _if = IfSchema.class) public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } @Schema(description = "if schema", deprecated = true) static class IfSchema { @Schema(_const = "foo") public String foo; @Schema(exclusiveMaximumValue = 2) public int bar; @Schema(types = {"string", "object"}) public int foobar; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore31/PetData.java ================================================ package io.swagger.v3.jaxrs2.petstore31; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class PetData { static List pets = new ArrayList(); static List categories = new ArrayList(); static { categories.add(createCategory(1, "Dogs")); categories.add(createCategory(2, "Cats")); categories.add(createCategory(3, "Rabbits")); categories.add(createCategory(4, "Lions")); pets.add(createPet(1, categories.get(1), "Cat 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(2, categories.get(1), "Cat 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "available")); pets.add(createPet(3, categories.get(1), "Cat 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "pending")); pets.add(createPet(4, categories.get(0), "Dog 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(5, categories.get(0), "Dog 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "sold")); pets.add(createPet(6, categories.get(0), "Dog 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "pending")); pets.add(createPet(7, categories.get(3), "Lion 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(8, categories.get(3), "Lion 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "available")); pets.add(createPet(9, categories.get(3), "Lion 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "available")); pets.add(createPet(10, categories.get(2), "Rabbit 1", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "available")); } public Pet getPetById(long petId) { for (Pet pet : pets) { if (pet.getId() == petId) { return pet; } } return null; } public List findPetByStatus(String status) { String[] statues = status.split(","); List result = new ArrayList(); for (Pet pet : pets) { for (String s : statues) { if (s.equals(pet.getStatus())) { result.add(pet); } } } return result; } public List findPetByCategory(Category category) { return pets.stream().filter(pet -> category.equals(pet.getCategory())).collect(Collectors.toList()); } public List findPetByTags(String tags) { String[] tagList = tags.split(","); List result = new ArrayList(); for (Pet pet : pets) { if (null != pet.getTags()) { for (Tag tag : pet.getTags()) { for (String tagListString : tagList) { if (tagListString.equals(tag.getName())) { result.add(pet); } } } } } return result; } public void addPet(Pet pet) { if (pets.size() > 0) { for (int i = pets.size() - 1; i >= 0; i--) { if (pets.get(i).getId() == pet.getId()) { pets.remove(i); } } } pets.add(pet); } static Pet createPet(long id, Category cat, String name, String[] urls, String[] tags, String status) { Pet pet = new Pet(); pet.setId(id); pet.setCategory(cat); pet.setName(name); if (null != urls) { List urlObjs = new ArrayList(); for (String urlString : urls) { urlObjs.add(urlString); } pet.setPhotoUrls(urlObjs); } List tagObjs = new ArrayList(); int i = 0; if (null != tags) { for (String tagString : tags) { i = i + 1; Tag tag = new Tag(); tag.setId(i); tag.setName(tagString); tagObjs.add(tag); } } pet.setTags(tagObjs); pet.setStatus(status); return pet; } static Category createCategory(long id, String name) { Category category = new Category(); category.setId(id); category.setName(name); return category; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore31/PetResource.java ================================================ package io.swagger.v3.jaxrs2.petstore31; import io.swagger.v3.jaxrs2.resources.QueryResultBean; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; @Consumes("application/json") @Path("/pet") @Produces({"application/json", "application/xml"}) public class PetResource { static PetData petData = new PetData(); @GET @Path("/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched"/*, _enum = "range[1,10]"*/, required = true) @PathParam("petId") final Long petId) throws NotFoundException { Pet pet = petData.getPetById(petId); if (null != pet) { return Response.ok().entity(pet).build(); } else { throw new NotFoundException(404, "Pet not found"); } } @POST @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPet( @Parameter(description = "Pet object that needs to be added to the store", required = true) final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodynoannotation") @Consumes({"application/json", "application/xml"}) @Produces({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store no annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetNoAnnotation(final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyid") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer with generic parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByInteger( @Parameter(description = "Pet object that needs to be added to the store", required = true) final int petId) { return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyidnoannotation") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer without parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByIntegerNoAnnotation(final int petId) { return Response.ok().entity("SUCCESS").build(); } @PUT @Operation(summary = "Update an existing pet", responses = { @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found"), @ApiResponse(responseCode = "405", description = "Validation exception")}) public Response updatePet( @Parameter(description = "Pet object that needs to be added to the store", required = true) final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @GET @Path("/findByStatus") @Produces("application/xml") @Operation(summary = "Finds Pets by status", description = "Multiple status values can be provided with comma separated strings", responses = { @ApiResponse( content = @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))), @ApiResponse( responseCode = "400", description = "Invalid status value" )} ) public Response findPetsByStatus( @Parameter(description = "Status values that need to be considered for filter", required = true) @QueryParam("status") final String status, @BeanParam final QueryResultBean qr ) { return Response.ok(petData.findPetByStatus(status)).build(); } @GET @Path("/findByTags") @Produces("application/json") @Operation(summary = "Finds Pets by tags", description = "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", responses = { @ApiResponse(description = "Pets matching criteria", content = @Content(schema = @Schema(implementation = Pet.class)) ), @ApiResponse(description = "Invalid tag value", responseCode = "400") }) @Deprecated public Response findPetsByTags( @Parameter(description = "Tags to filter by", required = true) @QueryParam("tags") final String tags) { return Response.ok(petData.findPetByTags(tags)).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore31/SimpleCategory.java ================================================ package io.swagger.v3.jaxrs2.petstore31; public class SimpleCategory {} ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore31/SimpleTag.java ================================================ package io.swagger.v3.jaxrs2.petstore31; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.media.Schema; public class SimpleTag { @Schema( properties = { @StringToClassMapItem(key = "foo", value = Foo.class) }, ref = "#/components/schemas/SimpleCategory", description = "child description" ) public Object annotated; @Schema(description = "Foo", deprecated = true) static class Foo { @Schema(_const = "foo") public String foo; @Schema(exclusiveMaximumValue = 2) public int bar; @Schema(types = {"string", "object"}) public int foobar; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore31/Tag.java ================================================ package io.swagger.v3.jaxrs2.petstore31; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.media.Schema; @XmlRootElement(name = "Tag") public class Tag { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @Schema( properties = { @StringToClassMapItem(key = "foo", value = Foo.class), @StringToClassMapItem(key = "bar", value = Bar.class) }, ref = "#/components/schemas/Category", description = "child description" ) public Object annotated; @Schema(description = "Foo", deprecated = true) static class Foo { @Schema(_const = "foo") public String foo; @Schema(exclusiveMaximumValue = 2) public int bar; @Schema(types = {"string", "object"}) public int foobar; } @Schema(description = "Bar", deprecated = true) static class Bar { @Schema(_const = "bar") public String foo; @Schema(exclusiveMaximumValue = 4) public int bar; @Schema(types = {"string", "integer"}) public int foobar; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore31/TagResource.java ================================================ package io.swagger.v3.jaxrs2.petstore31; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/tag") public class TagResource { @GET @Path("/tag") public SimpleTag getTag(@RequestBody SimpleCategory category) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/petstore31/User.java ================================================ package io.swagger.v3.jaxrs2.petstore31; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "User") public class User { private long id; private String username; private String firstName; private String lastName; private String email; private String password; private String phone; private int userStatus; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "firstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement(name = "lastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone") public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @XmlElement(name = "userStatus") @Schema(description = "User Status") //, allowableValues = {"1","2","3"}) public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Address.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.DependentRequired; import io.swagger.v3.oas.annotations.media.Schema; @Schema( _if = Address.AnnotatedCountry.class, then = PostalCodeNumberPattern.class, _else = PostalCodePattern.class, propertyNames = Address.PropertyNamesPattern.class, dependentRequiredMap = { @DependentRequired( name = "street", value = { "country" } ) } ) public class Address { private String street; private CountryEnum country; public enum CountryEnum { UNITED_STATES_OF_AMERICA("United States of America"), CANADA("Canada"); private String value; CountryEnum(String value) { this.value = value; } public String getValue() { return value; } @Override public String toString() { return String.valueOf(value); } public static CountryEnum fromValue(String value) { for (CountryEnum b : CountryEnum.values()) { if (b.value.equals(value)) { return b; } } return null; } } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public CountryEnum getCountry() { return country; } public void setCountry(CountryEnum country) { this.country = country; } class AnnotatedCountry { private Object country; @Schema( _const = "United States" ) public Object getCountry() { return country; } public void setCountry(Object country) { this.country = country; } } @Schema( pattern = "^[A-Za-z_][A-Za-z0-9_]*$" ) class PropertyNamesPattern { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ArraySchemaImplementationResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.List; public class ArraySchemaImplementationResource { static class Pet { @ArraySchema(schema = @Schema(implementation = Integer.class, description = "A house in a street")) public List cars; } @GET @Path("/test") public Pet test() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/BasicClass.java ================================================ package io.swagger.v3.jaxrs2.resources; public class BasicClass { public void emptyMethod() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/BasicFieldsResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.Category; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; public class BasicFieldsResource { @GET @Path("/1") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response getSummaryAndDescription(@QueryParam("subscriptionId") @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, description = "parameter description", allowEmptyValue = true, allowReserved = true, schema = @Schema( description = "the generated UUID", type = "string", format = "uuid", accessMode = Schema.AccessMode.READ_ONLY) ) String subscriptionId) { return Response.ok().entity("ok").build(); } @GET @Path("/2") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response getSummaryAndDescription2(@QueryParam("subscriptionId") @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, description = "parameter description", allowEmptyValue = true, allowReserved = true, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = Category.class, description = "the generated UUID"), uniqueItems = true) ) String subscriptionId) { return Response.ok().entity("ok").build(); } @GET @Path("/3") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response getSummaryAndDescription3(@QueryParam("subscriptionId") @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, description = "parameter description", allowEmptyValue = true, allowReserved = true, schema = @Schema( implementation = Category.class, description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY) ) String subscriptionId) { return Response.ok().entity("ok").build(); } @GET @Path("/4") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response getSummaryAndDescription4(@QueryParam("subscriptionId") @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, description = "parameter description", allowEmptyValue = true, allowReserved = true, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(format = "uuid", description = "the generated UUID"), uniqueItems = true) ) String subscriptionId) { return Response.ok().entity("ok").build(); } @GET @Path("/5") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response getSummaryAndDescription5(@QueryParam("subscriptionId") @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, description = "parameter description", allowEmptyValue = true, allowReserved = true, content = @Content(mediaType = "application/json") ) String subscriptionId) { return Response.ok().entity("ok").build(); } @GET @Path("/6") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response getSummaryAndDescription6( @Parameter( schema = @Schema(description = "test") ) String subscriptionId) { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/BinaryParameterResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import io.swagger.v3.jaxrs2.resources.model.Item; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @Path("/") public class BinaryParameterResource { @Consumes({ MediaType.APPLICATION_JSON }) @Path("/binary") @POST @Operation( summary = "Create new item", description = "Post operation with entity in a body", responses = { @ApiResponse( content = @Content( schema = @Schema(implementation = Item.class), mediaType = MediaType.APPLICATION_JSON ), headers = @Header(name = "Location"), responseCode = "201" ) } ) public Response createItem(@Context final UriInfo uriInfo, @Parameter(required = true) final Item item) { return Response .created(uriInfo.getBaseUriBuilder().path(item.getName()).build()) .entity(item).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/BookStoreTicket2646.java ================================================ package io.swagger.v3.jaxrs2.resources; import java.util.Arrays; import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @Path("/bookstore") public class BookStoreTicket2646 { @Produces({ MediaType.APPLICATION_JSON }) @GET public Response getBooks( @QueryParam("page") @DefaultValue("1") int page) { return Response.ok( Arrays.asList( new Book(), new Book() ) ).build(); } @Produces({ MediaType.APPLICATION_JSON }) @Path("/{id}") @GET public Book getBook(@PathParam("id") Long id) { return new Book(); } @Path("/{id}") @DELETE public Response delete(@PathParam("id") String id) { return Response.ok().build(); } public static class Book { public String foo; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ClassPathParentResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.Path; @Path("/v1") public class ClassPathParentResource { @Path("parent") public ClassPathSubResource getSubResource() { return new ClassPathSubResource(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ClassPathSubResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.info.Info; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @OpenAPIDefinition(info = @Info(description = "Subresource Class")) @Path("subresource") public class ClassPathSubResource { @GET @Operation(operationId = "get Code") public String getCode() { return "400"; } @GET @Path("{id}") public String getWidget(@PathParam("id") String id) { return "widget"; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Client.java ================================================ package io.swagger.v3.jaxrs2.resources; public class Client { private String name; private int creditCard; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getCreditCard() { return creditCard; } public void setCreditCard(int creditCard) { this.creditCard = creditCard; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/CompleteFieldsResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; public class CompleteFieldsResource { @GET @Path("/") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description", tags = {"Example Tag", "Second Tag"}, externalDocs = @ExternalDocumentation( description = "External documentation description", url = "http://url.com" ), parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, description = "parameter description", allowReserved = true, schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY) )}, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema(implementation = ResponsesResource.SampleResponseSchema.class) ) ), @ApiResponse( responseCode = "default", description = "boo", content = @Content( mediaType = "*/*", schema = @Schema(implementation = ResponsesResource.GenericError.class) ) ) } ) public Response getSummaryAndDescription() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/CreditCard.java ================================================ package io.swagger.v3.jaxrs2.resources; public class CreditCard { private String billingAddress; public String getBillingAddress() { return billingAddress; } public void setBillingAddress(String billingAddress) { this.billingAddress = billingAddress; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/DefaultResponseResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; public class DefaultResponseResource { @GET @Path("/") public String test() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/DeprecatedFieldsResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; public class DeprecatedFieldsResource { @GET @Path("/") @Operation(deprecated = true) public Response deprecatedMethod() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/DuplicatedOperationIdResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; public class DuplicatedOperationIdResource { @GET @Path("/") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response getSummaryAndDescription() { return Response.ok().entity("ok").build(); } @POST @Path("/") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response postSummaryAndDescription() { return Response.ok().entity("ok").build(); } @GET @Path("/path") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response getDuplicatedOperation() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/DuplicatedOperationMethodNameResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; public class DuplicatedOperationMethodNameResource { @GET @Path("/1") @Operation(operationId = "getSummaryAndDescription2", summary = "Operation Summary", description = "Operation Description") public Response getSummaryAndDescription1() { return Response.ok().entity("ok").build(); } @GET @Path("/2") public Response getSummaryAndDescription2() { return Response.ok().entity("ok").build(); } @POST @Path("/2") @Operation(operationId = "postSummaryAndDescription3", summary = "Operation Summary", description = "Operation Description") public Response postSummaryAndDescription2() { return Response.ok().entity("ok").build(); } @GET @Path("/3") public Response getSummaryAndDescription3() { return Response.ok().entity("ok").build(); } @POST @Path("/3") public Response postSummaryAndDescription3() { return Response.ok().entity("ok").build(); } @GET @Path("/4") public Response getSummaryAndDescription3(String foo) { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/DuplicatedSecurityResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.security.OAuthFlow; import io.swagger.v3.oas.annotations.security.OAuthFlows; import io.swagger.v3.oas.annotations.security.OAuthScope; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityScheme; import javax.ws.rs.GET; import javax.ws.rs.Path; @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, description = "myOauthSecurity Description", flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "http://x.com", scopes = @OAuthScope( name = "write:pets", description = "modify pets in your account")) ) ) @SecurityScheme(name = "myOauth2Security2", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, description = "myOauthSecurity Description2", flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "http://x.com", scopes = @OAuthScope( name = "write:pets", description = "modify pets in your account")) ) ) @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, description = "myOauthSecurity Description3", flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "http://x.com", scopes = @OAuthScope( name = "write:pets", description = "modify pets in your account")) ) ) public class DuplicatedSecurityResource { @GET @Path("/") @Operation(operationId = "Operation Id", description = "description") @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) public void getSecurity() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/EnhancedResponsesResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class EnhancedResponsesResource implements ResponsesInterface{ @GET @Path("/") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output object", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "404", description = "not found!" )} ) @ApiResponse( responseCode = "400", description = "boo", content = @Content( mediaType = "*/*", schema = @Schema(implementation = GenericError.class) ) ) public void getResponses() { } static class SampleResponseSchema { @Schema(description = "the user id") private String id; } static class GenericError { private int code; private String message; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/EnumParameterResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; public class EnumParameterResource { @GET @Path("/task") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiResponse(responseCode = "200", content = { @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(type = "array", implementation = TaskDTO.class))) }) @ApiResponse(responseCode = "404", description = "User not found") @Operation(parameters = { @Parameter(in = ParameterIn.QUERY, name = "guid", required = true), }) public Response getTasks(@QueryParam("tasktype") TaskType taskType, @Context SecurityContext securityContext) { return null; } public enum TaskType { A, B } public class TaskDTO { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ExternalDocsReference.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.GET; import javax.ws.rs.Path; @ExternalDocumentation( description = "External documentation description in class", url = "http://url.com" ) public class ExternalDocsReference { @GET @Path("/") @Operation(externalDocs = @ExternalDocumentation( description = "External documentation description in @Operation", url = "http://url.com" ) ) @ExternalDocumentation( description = "External documentation description in method", url = "http://url.com" ) public void setRequestBody(@RequestBody ExternalDocsSchema schema) { } @Schema(externalDocs = @ExternalDocumentation( description = "External documentation description in schema", url = "http://url.com" )) public class ExternalDocsSchema { public String foo; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/GenericResponsesResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.ArrayList; import java.util.List; public class GenericResponsesResource { @GET @Path("/") @Operation( operationId = "getSomethings", summary = "Returns a list of somethings", responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = SomethingResponse.class))) } ) public void getResponses() { } @GET @Path("/overridden") @Operation( operationId = "getSomethingsOverridden", summary = "Returns a list of somethings", responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = SomethingDTO.class))) } ) public void getResponsesWithOverriddenName() { } class SomethingResponse extends JsonResponse { } public class JsonResponse { private DataWithCursor data; public JsonResponse() { } public JsonResponse(DataWithCursor data) { this.data = data; } public Data getData() { return data; } } public class DataWithCursor extends Data { private String previousCursor; private String nextCursor; public DataWithCursor(List data, String previousCursor, String nextCursor) { super(data); this.previousCursor = previousCursor; this.nextCursor = nextCursor; } public DataWithCursor(List data) { super(data); } public String getPreviousCursor() { return previousCursor; } public String getNextCursor() { return nextCursor; } } public class Data { private List items; private Data() { } public Data(List items) { this.items = items; } public Data(T item) { items = new ArrayList<>(); items.add(item); } public List getItems() { return items; } } @Schema(name = "Something") public class SomethingDTO { private String id; public SomethingDTO(SomethingAlt somethingAlt) { id = somethingAlt.getId(); } public String getId() { return id; } } public class SomethingAlt { private String id; public String getId() { return id; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/HiddenAnnotatedUserResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.data.UserData; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; @Path("/user") @Produces({"application/json", "application/xml"}) @Hidden public class HiddenAnnotatedUserResource { static UserData userData = new UserData(); @POST @Operation(hidden = true, summary = "Create user", description = "This can only be done by the logged in user.") public Response createUser( @Parameter(description = "Created user object", required = true) User user) { userData.addUser(user); return Response.ok().entity("").build(); } @Path("/user") @Produces({"application/json", "application/xml"}) public class HiddenAnnotatedUserResourceMethodAndData { UserData userData = new UserData(); @POST @Hidden @Operation(summary = "Create user", description = "This can only be done by the logged in user.") @Path("/1") public Response createUser( @Parameter(description = "Created user object", required = true) User user) { userData.addUser(user); return Response.ok().entity("").build(); } @POST @Operation(summary = "Create user", description = "This can only be done by the logged in user.") @Path("/2") public Response createUserWithHiddenBeanProperty( @Parameter(description = "Created user object", required = true) UserResourceBean user) { return Response.ok().entity("").build(); } } public class UserResourceBean { @Hidden public HiddenAnnotatedUserResourceBean id; public String foo; } public class HiddenAnnotatedUserResourceBean { public String id; public String foo; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/HiddenUserResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.data.UserData; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; @Path("/user") @Produces({"application/json", "application/xml"}) public class HiddenUserResource { static UserData userData = new UserData(); @POST @Operation(hidden = true, summary = "Create user", description = "This can only be done by the logged in user.") public Response createUser( @Parameter(description = "Created user object", required = true) User user) { userData.addUser(user); return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/JsonIdentityCyclicResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.ModelWithJsonIdentityCyclic; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; @Path("/pet") @Produces({"application/json", "application/xml"}) public class JsonIdentityCyclicResource { @POST @Operation(description = "Add a single object") public Response test( @Parameter(required = true) ModelWithJsonIdentityCyclic model) { return Response.ok().entity("SUCCESS").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/JsonIdentityResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.ModelWithJsonIdentity; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; @Path("/pet") @Produces({"application/json", "application/xml"}) public class JsonIdentityResource { @POST @Operation(description = "Add a single object") public Response test( @Parameter(required = true) ModelWithJsonIdentity model) { return Response.ok().entity("SUCCESS").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Misc31Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Path("/pet") @Produces({"application/json", "application/xml"}) public class Misc31Resource { @PUT public ModelWithOAS31Stuff updatePet(){ return null;} } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ModelWithOAS31Stuff.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.MultipleBaseBean; import io.swagger.v3.oas.annotations.StringToClassMapItem; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; @Schema( $id = "http://yourdomain.com/schemas/myschema.json", description = "this is model for testing OAS 3.1 resolving", $comment = "Random comment at schema level", types = {"object"} ) public class ModelWithOAS31Stuff { private List randomList; private Object status; private int intValue; private String text; private String encodedString; private Address address; private Client client; @ArraySchema( maxContains = 10, minContains = 1, contains = @Schema( types = "string" ), unevaluatedItems = @Schema( types = "number" ), prefixItems = { @Schema( types = "string" ) } ) public List getRandomList() { return randomList; } public void setRandomList(List randomList) { this.randomList = randomList; } @Schema(types = { "string", "number" }) public Object getStatus() { return status; } public void setStatus(Object status) { this.status = status; } @Schema( $anchor = "intValue", $comment = "comment at schema property level", exclusiveMaximumValue = 100, exclusiveMinimumValue = 1 ) public int getIntValue() { return intValue; } public void setIntValue(int intValue) { this.intValue = intValue; } @Schema( contentEncoding = "plan/text", contentMediaType = "base64" ) public String getText() { return text; } public void setText(String text) { this.text = text; } @Schema( contentMediaType = "application/jwt", contentSchema = MultipleBaseBean.class ) public String getEncodedString() { return encodedString; } public void setEncodedString(String encodedString) { this.encodedString = encodedString; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Schema( dependentSchemas = { @StringToClassMapItem( key = "creditCard", value = CreditCard.class ) } ) public String getClient() { return null; } public void setClient(String client) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/MyClass.java ================================================ package io.swagger.v3.jaxrs2.resources; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; public class MyClass extends MySuperClass { public void populate(final String isotonicDrink, final String softDrink, final String isoDrink, final String isotonicDrinkOnlyXmlElement) { this.isotonicDrink = isotonicDrink; this.softDrink = softDrink; this.isoDrink = isoDrink; this.isotonicDrinkOnlyXmlElement = isotonicDrinkOnlyXmlElement; } @XmlElement(name = "beerDrink") @JsonProperty("beerDrink") private String isotonicDrink; @XmlElement(name = "sugarDrink") private String softDrink; @Schema(name = "saltDrink") private String isoDrink; @XmlElement(name = "beerDrinkXmlElement") private String isotonicDrinkOnlyXmlElement; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/MyOtherClass.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; public class MyOtherClass extends MySuperClass { public void populate(final String myPropertyName) { this.myProperty = myPropertyName; } @XmlElement(name = "MyPrOperTyName") @XmlAttribute(name = "MyPrOperTyName") private String myProperty; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/MySuperClass.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(XmlAccessType.FIELD) public class MySuperClass { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/NoPathSubResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; /** * The {@code NoPathSubResource} class defines test sub-resource without * {@link javax.ws.rs.Path} annotations. */ public class NoPathSubResource { @Operation(description = "Returns greeting") @GET public String getGreeting() { return "Hello!"; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ParameterMaximumValueResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import java.util.List; @Path("/test") public class ParameterMaximumValueResource { @GET @Path("/{petId}") public Response getPetById( @Parameter( description = "ID of pet that needs to be fetched", schema = @Schema( type = "integer", format = "int64", exclusiveMinimumValue = 1, exclusiveMaximumValue = 10 ), required = true) @PathParam("petId") Long petId) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ParametersResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class ParametersResource { @GET @Path("/") @Operation(parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, description = "parameter description", allowReserved = true, schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY) )} ) public void getParameters(@QueryParam("subscriptionId") String subscriptionId) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/PetResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.data.PetData; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.Category; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.MatrixParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; @Consumes("application/json") @Path("/pet") @Produces({"application/json", "application/xml"}) public class PetResource { static PetData petData = new PetData(); @GET @Path("/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched"/*, _enum = "range[1,10]"*/, required = true) @PathParam("petId") Long petId) throws NotFoundException { Pet pet = petData.getPetById(petId); if (null != pet) { return Response.ok().entity(pet).build(); } else { throw new NotFoundException(404, "Pet not found"); } } @POST @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPet( @Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodynoannotation") @Consumes({"application/json", "application/xml"}) @Produces({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store no annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetNoAnnotation(Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyid") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer with generic parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByInteger( @Parameter(description = "Pet object that needs to be added to the store", required = true) int petId) { return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyidnoannotation") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer without parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByIntegerNoAnnotation(int petId) { return Response.ok().entity("SUCCESS").build(); } @PUT @Operation(summary = "Update an existing pet", responses = { @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found"), @ApiResponse(responseCode = "405", description = "Validation exception")}) public Response updatePet( @Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @GET @Path("/findByStatus") @Produces("application/xml") @Operation(summary = "Finds Pets by status", description = "Multiple status values can be provided with comma separated strings", responses = { @ApiResponse( content = @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))), @ApiResponse( responseCode = "400", description = "Invalid status value" )} ) public Response findPetsByStatus( @Parameter(description = "Status values that need to be considered for filter", required = true/*, defaultValue = "available", allowableValues = "available,pending,sold", allowMultiple = true*/) @QueryParam("status") String status, @BeanParam QueryResultBean qr ) { return Response.ok(petData.findPetByStatus(status)).build(); } @GET @Path("/findByCategory/{category}") @Produces("application/xml") @Operation(summary = "Finds Pets by category", responses = { @ApiResponse( content = @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))), @ApiResponse( responseCode = "400", description = "Invalid category value" )} ) public Response findPetsByCategory( @Parameter(description = "Category value that need to be considered for filter", required = true) @MatrixParam("category") Category category, @BeanParam QueryResultBean qr ) { return Response.ok(petData.findPetByCategory(category)).build(); } @GET @Path("/findByTags") @Produces("application/json") @Operation(summary = "Finds Pets by tags", description = "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", responses = { @ApiResponse(description = "Pets matching criteria", content = @Content(schema = @Schema(implementation = Pet.class)) ), @ApiResponse(description = "Invalid tag value", responseCode = "400") }) @Deprecated public Response findPetsByTags( @Parameter(description = "Tags to filter by", required = true/*, allowMultiple = true*/) @QueryParam("tags") String tags) { return Response.ok(petData.findPetByTags(tags)).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/PetResourceSlashesinPath.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.data.PetData; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.Category; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.MatrixParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; @Consumes("application/json") @Path("pet") @Produces({"application/json", "application/xml"}) public class PetResourceSlashesinPath { static PetData petData = new PetData(); @GET @Path("/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched"/*, _enum = "range[1,10]"*/, required = true) @PathParam("petId") Long petId) throws NotFoundException { Pet pet = petData.getPetById(petId); if (null != pet) { return Response.ok().entity(pet).build(); } else { throw new NotFoundException(404, "Pet not found"); } } @POST @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPet( @Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("bodynoannotation") @Consumes({"application/json", "application/xml"}) @Produces({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store no annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetNoAnnotation(Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyid/") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer with generic parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByInteger( @Parameter(description = "Pet object that needs to be added to the store", required = true) int petId) { return Response.ok().entity("SUCCESS").build(); } @POST @Path("bodyidnoannotation/") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer without parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByIntegerNoAnnotation(int petId) { return Response.ok().entity("SUCCESS").build(); } @PUT @Operation(summary = "Update an existing pet", responses = { @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found"), @ApiResponse(responseCode = "405", description = "Validation exception")}) public Response updatePet( @Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @GET @Path("/findByStatus") @Produces("application/xml") @Operation(summary = "Finds Pets by status", description = "Multiple status values can be provided with comma separated strings", responses = { @ApiResponse( content = @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))), @ApiResponse( responseCode = "400", description = "Invalid status value" )} ) public Response findPetsByStatus( @Parameter(description = "Status values that need to be considered for filter", required = true/*, defaultValue = "available", allowableValues = "available,pending,sold", allowMultiple = true*/) @QueryParam("status") String status, @BeanParam QueryResultBean qr ) { return Response.ok(petData.findPetByStatus(status)).build(); } @GET @Path("/findByTags") @Produces("application/json") @Operation(summary = "Finds Pets by tags", description = "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", responses = { @ApiResponse(description = "Pets matching criteria", content = @Content(schema = @Schema(implementation = Pet.class)) ), @ApiResponse(description = "Invalid tag value", responseCode = "400") }) @Deprecated public Response findPetsByTags( @Parameter(description = "Tags to filter by", required = true/*, allowMultiple = true*/) @QueryParam("tags") String tags) { return Response.ok(petData.findPetByTags(tags)).build(); } @GET @Path("/findByCategory/{category}") @Produces("application/xml") @Operation(summary = "Finds Pets by category", responses = { @ApiResponse( content = @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))), @ApiResponse( responseCode = "400", description = "Invalid category value" )} ) public Response findPetsByCategory( @Parameter(description = "Category value that need to be considered for filter", required = true) @MatrixParam("category") Category category, @BeanParam QueryResultBean qr ) { return Response.ok(petData.findPetByCategory(category)).build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/PostalCodeNumberPattern.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.Schema; public class PostalCodeNumberPattern { private Object postalCode; @Schema( pattern = "[0-9]{5}(-[0-9]{4})?" ) public Object getPostalCode() { return postalCode; } public void setPostalCode(Object postalCode) { this.postalCode = postalCode; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/PostalCodePattern.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.Schema; public class PostalCodePattern { private Object postalCode; @Schema( pattern = "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" ) public Object getPostalCode() { return postalCode; } public void setPostalCode(Object postalCode) { this.postalCode = postalCode; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/QueryResultBean.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.QueryParam; public class QueryResultBean { @QueryParam("skip") private Integer skip; @QueryParam("limit") private Integer limit; public Integer getSkip() { return skip; } public void setSkip(Integer skip) { this.skip = skip; } public Integer getLimit() { return limit; } public void setLimit(Integer limit) { this.limit = limit; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ReaderListenerResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.ReaderListener; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.integration.api.OpenApiReader; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; public class ReaderListenerResource implements ReaderListener { @GET @Path("/") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description") public Response getSummaryAndDescription(@QueryParam("subscriptionId") @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, description = "parameter description", allowEmptyValue = true, allowReserved = true, schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY) ) String subscriptionId, @QueryParam("description") String description) { return Response.ok().entity("ok").build(); } @Override public void beforeScan(OpenApiReader reader, OpenAPI openAPI) { openAPI.addTagsItem(new Tag().name("Tag-added-before-read")); } @Override public void afterScan(OpenApiReader reader, OpenAPI openAPI) { openAPI.addTagsItem(new Tag().name("Tag-added-after-read")); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefCallbackResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class RefCallbackResource { @Callbacks({ @Callback( name = "testCallback1", ref = "Callback", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/simplecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefExamplesResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.petstore.example.SubscriptionResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.POST; import javax.ws.rs.Path; /** * Examples Resource Scenario */ public class RefExamplesResource { @Path("/example") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(name = "Schema", description = "Schema", example = "Subscription example"), style = ParameterStyle.SIMPLE, example = "example", examples = { @ExampleObject(name = "subscriptionId_1", value = "12345", summary = "Subscription number 12345", externalValue = "Subscription external value 1" , ref = "Id") }) }) public SubscriptionResponse subscribe(final int subscriptionId) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefHeaderResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Class with Links */ public class RefHeaderResource { @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", headers = {@Header( name = "Rate-Limit-Limit", description = "The number of allowed requests in the current period", ref = "Header", schema = @Schema(type = "integer"))}) }) @GET @Path("/path") public void simpleGet() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefLinksResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with Links */ public class RefLinksResource { @Path("/links") @Operation(operationId = "getUserWithAddress", responses = { @ApiResponse(description = "test description", content = @Content(mediaType = "*/*", schema = @Schema(ref = "#/components/schemas/User")), links = { @Link( name = "address", operationId = "getAddress", ref = "Link", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) })} ) @GET public String getUser(@QueryParam("userId")final String userId) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefParameter3029Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; public class RefParameter3029Resource { @GET @Path("/1") @Operation( summary = "Simple get operation", operationId = "sendPayload1", parameters = @Parameter(ref = "id")) public void sendPayload1() { } @GET @Path("/2") @Operation( summary = "Simple get operation", operationId = "sendPayload2") @Parameter(ref = "id") public void sendPayload2() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefParameter3074Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import javax.ws.rs.GET; import javax.ws.rs.Path; public class RefParameter3074Resource { public static final String EXPECTED_YAML_WITHOUT_WRAPPER = "openapi: 3.0.1\n" + "paths:\n" + " /employee:\n" + " get:\n" + " summary: Get an employee\n" + " operationId: getEmployee\n" + " responses:\n" + " \"200\":\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Employee\"\n" + " \"500\":\n" + " content:\n" + " application/json:\n" + " schema:\n" + " $ref: \"#/components/schemas/Error\"\n" + "components:\n" + " schemas:\n" + " Employee:\n" + " type: object\n" + " Error:\n" + " type: object"; public static final String EXPECTED_YAML_WITH_WRAPPER = EXPECTED_YAML_WITHOUT_WRAPPER + "\n Wrapper:\n type: object"; class Wrapper { final A a; Wrapper(A a) { this.a = a; } } class Employee { int number; String name; Employee(int number, String name) { this.number = number; this.name = name; } } class Error { String message; } @GET @Path("/employee") @Operation(summary = "Get an employee") @ApiResponses({ @ApiResponse( responseCode = "200", content = @Content(schema = @Schema(implementation = Employee.class), mediaType = "application/json") ), @ApiResponse( responseCode = "500", content = @Content(schema = @Schema(implementation = Error.class), mediaType = "application/json") ), }) public Wrapper getEmployee() { return new Wrapper(new Employee(1, "Michael Suyama")); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefParameterResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class RefParameterResource { @GET @Path("/") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with a payload complex input object", operationId = "sendPayload", deprecated = true ) public void sendPayload(@Parameter(ref = "id") @QueryParam("id") final int id) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefRequestBodyResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.GET; import javax.ws.rs.Path; public class RefRequestBodyResource { @GET @Path("/") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with a payload complex input object", operationId = "sendPayload", deprecated = true, requestBody = @RequestBody(ref = "User") ) public void sendPayload(final User user) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefResponsesResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class RefResponsesResource { @GET @Path("/") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output object", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema(implementation = SampleResponseSchema.class) ) ), @ApiResponse( description = "boo", content = @Content( mediaType = "*/*", schema = @Schema(implementation = GenericError.class) ) ), @ApiResponse( responseCode = "401", ref = "invalidJWT" ) } ) public void getResponses() { } static class SampleResponseSchema { @Schema(description = "the user id") private String id; } static class GenericError { private int code; private String message; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/RefSecurityResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.security.*; import javax.ws.rs.GET; import javax.ws.rs.Path; @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, description = "myOauthSecurity Description", ref = "Security", flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "http://x.com", scopes = @OAuthScope( name = "write:pets", description = "modify pets in your account")) ) ) public class RefSecurityResource { @GET @Path("/") @Operation(operationId = "Operation Id", description = "description") @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) public void getSecurity() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ResourceWithJacksonBean.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.JacksonBean; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Path("test") @Produces("application/json") public class ResourceWithJacksonBean { @POST @Path("/document/{documentName}.json") @Operation(operationId = "uploadAttachAndParseUserDocument", description = "Uploads, parses, and attaches the document to the user's job application.") public String uploadDocument(JacksonBean bean) throws Exception { return ""; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ResourceWithKnownInjections.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.servlet.ServletConfig; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; @Path("/resource/{id}") @Produces({"application/json", "application/xml"}) public class ResourceWithKnownInjections { private Integer constructorParam; @QueryParam("fieldParam") private String fieldParam; // injection into a class field @Parameter(hidden = true) @QueryParam("hiddenParam") private String hiddenParam; // injection into a constructor parameter public ResourceWithKnownInjections(@PathParam("id") Integer constructorParam, @QueryParam("hiddenParam") @Parameter(hidden = true) String hiddenParam, @Context ServletConfig context) { this.constructorParam = constructorParam; } private ResourceWithKnownInjections(@PathParam("id") Integer constructorParam, @QueryParam("fakeParam") String fakeParam) { this.constructorParam = constructorParam; } @GET @Operation public String get(@QueryParam("methodParam") String methodParam) { // injection into a resource method parameter final StringBuilder sb = new StringBuilder(); sb.append("Constructor param: ").append(constructorParam).append("\n"); sb.append("Field param: ").append(fieldParam).append("\n"); sb.append("Method param: ").append(methodParam).append("\n"); return sb.toString(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ResourceWithSubResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Path; @Path("/employees") public class ResourceWithSubResource { @Operation(description = "gets all employees", tags = "Employees") @ApiResponse(description = "200", responseCode = "200", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Pet.class)))) @Path("/{id}") public SubResource getTest() { return new SubResource(); } @Path("noPath") @Operation(description = "Returns sub-resource without @Path") public NoPathSubResource getNoPathTest() { return new NoPathSubResource(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ResponseContentWithArrayResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.List; public class ResponseContentWithArrayResource { @Operation( summary = "Get a list of users", description = "Get a list of users registered in the system", responses = {@ApiResponse( responseCode = "200", description = "The response for the user request", content = { @Content( mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = User.class)) ) }) } ) @GET @SecurityRequirement(name = "JWT") @Path("/user") public List getUsers() { return null; } class User { public String foo; @ArraySchema(arraySchema = @Schema(required = true), schema = @Schema(type = "string")) public List issue3438; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ResponseReturnTypeResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/sample") public interface ResponseReturnTypeResource { @GET @Path("/{id}") @Operation(summary = "Find by id", description = "Find by id operation") @ApiResponse(responseCode = "200", description = "Ok", useReturnTypeSchema = true) @ApiResponse(responseCode = "201", description = "201", useReturnTypeSchema = true, content = @Content(mediaType = "application/json")) @ApiResponse(responseCode = "204", description = "No Content", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Void.class))) TestDTO find(@Parameter(description = "ID") @PathParam("id") Integer id); @GET @Path("/{id}/default") @Operation(summary = "Find by id (default)", description = "Find by id operation (default)") TestDTO findDefault(@Parameter(description = "ID") @PathParam("id") Integer id); class TestDTO { public String foo; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ResponsesInterface.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema(implementation = ResponsesInterface.SampleResponseSchema.class) ) ) public interface ResponsesInterface { class SampleResponseSchema { @Schema(description = "the user id") private String id; } class GenericError { private int code; private String message; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ResponsesResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.MultipleBaseBean; import io.swagger.v3.jaxrs2.resources.model.MultipleSub1Bean; import io.swagger.v3.jaxrs2.resources.model.MultipleSub2Bean; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; public class ResponsesResource { @GET @Path("/") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output object", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema(implementation = SampleResponseSchema.class) ) ), @ApiResponse( description = "boo", content = @Content( mediaType = "*/*", schema = @Schema(implementation = GenericError.class) ) ) } ) public void getResponses() { } @GET @Path("/oneOf") @Operation(summary = "Test inheritance / polymorphism", responses = { @ApiResponse(description = "bean answer", responseCode = "200", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema( oneOf = { MultipleSub1Bean.class, MultipleSub2Bean.class } ) ) ) }) @Produces({ MediaType.APPLICATION_JSON }) public MultipleBaseBean getOneOf( @Context HttpServletRequest req, @Parameter(description = "Test inheritance / polymorphism", required = true, example = "1") @QueryParam("number") final int beanNumber) { return null; } @GET @Path("/anyOf") @Operation(summary = "Test inheritance / polymorphism", responses = { @ApiResponse(description = "bean answer", responseCode = "200", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema( anyOf = { MultipleSub1Bean.class, MultipleSub2Bean.class } ) ) ) }) @Produces({ MediaType.APPLICATION_JSON }) public MultipleBaseBean getAnyOf( @Context HttpServletRequest req, @Parameter(description = "Test inheritance / polymorphism", required = true, example = "1") @QueryParam("number") final int beanNumber) { return null; } @GET @Path("/allOf") @Operation(summary = "Test inheritance / polymorphism", responses = { @ApiResponse(description = "bean answer", responseCode = "200", content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema( allOf = { MultipleSub1Bean.class, MultipleSub2Bean.class } ) ) ) }) @Produces({ MediaType.APPLICATION_JSON }) public MultipleBaseBean getAllOf( @Context HttpServletRequest req, @Parameter(description = "Test inheritance / polymorphism", required = true, example = "1") @QueryParam("number") final int beanNumber) { return null; } static class SampleResponseSchema { @Schema(description = "the user id") private String id; } static class GenericError { private int code; private String message; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SchemaAdditionalPropertiesBooleanResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; public class SchemaAdditionalPropertiesBooleanResource { @Schema(additionalProperties = Schema.AdditionalPropertiesValue.FALSE) static class Pet { @Schema(additionalPropertiesSchema = Bar.class) public Bar bar; @Schema(additionalProperties = Schema.AdditionalPropertiesValue.FALSE) public Bar vbar; } static class Bar { public String foo; } @Schema(description = "A car") static class Car { public String foo; } @GET @Path("/test") public Pet test() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SchemaAdditionalPropertiesResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; import java.util.List; import java.util.Map; public class SchemaAdditionalPropertiesResource { static class Pet { public String foo; } @GET @Path("/fromtResponseType") public Map> fromtResponseType() { return null; } @GET @Path("/schemaNotImpl") @Operation( operationId = "schemaNotImpl", responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema( type = "object" ), additionalPropertiesSchema = @Schema( ref = "#/components/schemas/Pet" ) ) ) } ) public Response schemaNotImpl() { return null; } @GET @Path("/schemaImpl") @Operation( operationId = "schemaImpl", responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema( type = "object", additionalPropertiesSchema = Pet.class ) ) ) } ) public Response schemaImpl() { return null; } @GET @Path("/arraySchemaImpl") @Operation( operationId = "arraySchemaImpl", responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", additionalPropertiesArraySchema = @ArraySchema( schema = @Schema( implementation = Pet.class ) ), schema = @Schema( type = "object" ) ) ) } ) public Response arraySchemaImpl() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SchemaPropertiesResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.MultipleBaseBean; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.SchemaProperty; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; public class SchemaPropertiesResource { @GET @Path("/") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output object", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schemaProperties = { @SchemaProperty( name = "foo", schema = @Schema( type = "integer", maximum = "1" ) ) } ) ), @ApiResponse( description = "boo", content = @Content( schema = @Schema( type = "object", description = "various properties", maxProperties = 3 ), mediaType = "application/json", schemaProperties = { @SchemaProperty( name = "foo", schema = @Schema( type = "integer", maximum = "1" ) ) } ) ), @ApiResponse( responseCode = "400", description = "additionalProperties schema", content = @Content( mediaType = "application/json", schema = @Schema( type = "object", maxProperties = 2 ), additionalPropertiesSchema = @Schema( type = "string" ) ) ), @ApiResponse( responseCode = "401", description = "additionalProperties boolean", content = @Content( mediaType = "application/json", schema = @Schema( type = "object", maxProperties = 2, additionalProperties = Schema.AdditionalPropertiesValue.FALSE ) ) ) } ) public void getResponses() { } @GET @Path("/one") @Produces({MediaType.APPLICATION_JSON}) public MultipleBaseBean requestBodySchemaPropertyNoSchema( @RequestBody( content = @Content( mediaType = "application/yaml", schemaProperties = { @SchemaProperty( name = "foo", schema = @Schema( type = "string" ) ) } ) ) Object body) { return null; } @GET @Path("/two") @Produces({MediaType.APPLICATION_JSON}) public MultipleBaseBean requestBodySchemaPropertySchema( @RequestBody( content = @Content( mediaType = "application/yaml", schema = @Schema( type = "object", requiredProperties = { "foo" } ), schemaProperties= { @SchemaProperty( name = "foo", schema = @Schema( type = "string" ) ) } ) ) Object body) { return null; } @GET @Path("/three") @Produces({MediaType.APPLICATION_JSON}) public MultipleBaseBean requestBodySchemaPropertySchemaArray( @RequestBody( content = @Content( mediaType = "application/yaml", array = @ArraySchema( schema = @Schema( type = "object", requiredProperties = { "foo" } ) ), schemaProperties = { @SchemaProperty( name = "foo", schema = @Schema( type = "string" ) ) } ) ) Object body) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SecurityResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.security.OAuthFlow; import io.swagger.v3.oas.annotations.security.OAuthFlows; import io.swagger.v3.oas.annotations.security.OAuthScope; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityScheme; import javax.ws.rs.GET; import javax.ws.rs.Path; @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, description = "myOauthSecurity Description", flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "http://x.com", scopes = @OAuthScope( name = "write:pets", description = "modify pets in your account")) ) ) @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) @SecurityRequirement(name = "myOauth2Security", scopes = {"write:pets"} ) public class SecurityResource { @GET @Path("/") @Operation(operationId = "Operation Id", description = "description") @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) public void getSecurity() { } @GET @Path("/2") @Operation(operationId = "Operation Id 2", description = "description 2") @SecurityRequirement(name = "security_key2", scopes = {"write:pets", "read:pets"} ) public void getSecurity2() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ServersResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.servers.ServerVariable; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @OpenAPIDefinition( servers = { @Server( description = "definition server 1", url = "http://definition1", variables = { @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}), @ServerVariable(name = "var2", description = "var 2", defaultValue = "1", allowableValues = {"1", "2"}) }) } ) @Server( description = "class server 1", url = "http://class1", variables = { @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}), @ServerVariable(name = "var2", description = "var 2", defaultValue = "1", allowableValues = {"1", "2"}) }) @Server( description = "class server 2", url = "http://class2", variables = { @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}) }) public class ServersResource { @GET @Path("/") @Operation(servers = { @Server( description = "operation server 1", url = "http://op1", variables = { @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}) }) }) @Server( description = "method server 1", url = "http://method1", variables = { @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}) }) @Server( description = "method server 2", url = "http://method2" ) public Response getServers() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SiblingPropResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.siblings.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import javax.ws.rs.Consumes; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Path("/pet") @Produces({"application/json", "application/xml"}) public class SiblingPropResource { @PUT @Operation(summary = "Update an existing pet", tags = {"pet"}, security = { @SecurityRequirement(name = "petstore_auth", scopes = {"write:pets", "read:pets"}), @SecurityRequirement(name = "mutual_tls", scopes = {}) }, responses = { @ApiResponse( responseCode = "200", description = "Successful operation", useReturnTypeSchema = true, content = { @Content( mediaType = "application/xml", schema = @Schema( accessMode = Schema.AccessMode.READ_ONLY, description = "A Pet in XML Format" ) ), @Content( mediaType = "application/json", schema = @Schema( accessMode = Schema.AccessMode.READ_ONLY, description = "A Pet in JSON Format" ) ) } ), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found"), @ApiResponse(responseCode = "405", description = "Validation exception") }) @Consumes({"application/json", "application/xml"}) public Pet updatePet( @RequestBody( description = "Pet object that needs to be updated in the store", required = true, useParameterTypeSchema = true, content = { @Content( mediaType = "application/json", schema = @Schema( accessMode = Schema.AccessMode.WRITE_ONLY, description = "A Pet in JSON Format", requiredProperties = {"id"} ) ), @Content( mediaType = "application/xml", schema = @Schema( accessMode = Schema.AccessMode.WRITE_ONLY, description = "A Pet in XML Format", requiredProperties = {"id"} ) ) } ) Pet pet) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SiblingsResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.siblings.Pet; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import java.util.List; @Path("/test") public class SiblingsResource { @GET @Schema(description = "Cart Pet") public Pet getCart() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SiblingsResourceRequestBody.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.siblings.PetSimple; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @Path("/test") public class SiblingsResourceRequestBody { @Path("/bodyimpl") @GET @Operation( requestBody = @RequestBody( description = "aaa", content = { @Content( mediaType = "application/json", schema = @Schema( description = "resource pet", implementation = PetSimple.class, accessMode = Schema.AccessMode.WRITE_ONLY)) })) public Response getBodyImpl(Object body) { return null; } @Path("/bodyimplparam") @GET public Response getBodyImplParam(@RequestBody( content = { @Content( mediaType = "*/*", schema = @Schema( description = "resource pet", implementation = PetSimple.class, accessMode = Schema.AccessMode.WRITE_ONLY)) }) Object body) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SiblingsResourceRequestBodyMultiple.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.siblings.PetSimple; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @Path("/test") public class SiblingsResourceRequestBodyMultiple { @Path("/bodyimpl") @GET @Operation( requestBody = @RequestBody( description = "aaa", content = { @Content( mediaType = "application/json", schema = @Schema( description = "resource pet", implementation = PetSimple.class, accessMode = Schema.AccessMode.WRITE_ONLY)), @Content( mediaType = "application/xml", schema = @Schema( description = "resource pet xml", implementation = PetSimple.class, accessMode = Schema.AccessMode.WRITE_ONLY)) })) public Response getBodyImpl(Object body) { return null; } @Path("/bodyimplparam") @GET public Response getBodyImplParam(@RequestBody( content = { @Content( mediaType = "application/json", schema = @Schema( description = "resource pet", implementation = PetSimple.class, accessMode = Schema.AccessMode.WRITE_ONLY)), @Content( mediaType = "application/xml", schema = @Schema( description = "resource pet xml", implementation = PetSimple.class, accessMode = Schema.AccessMode.WRITE_ONLY)) }) Object body) { return null; } @Path("/bodyparam") @GET public Response getBodyParam( @RequestBody( description = "test", useParameterTypeSchema = true, content = { @Content( mediaType = "application/json", schema = @Schema( description = "resource pet", accessMode = Schema.AccessMode.WRITE_ONLY)), @Content( mediaType = "application/xml", schema = @Schema( description = "resource pet xml", accessMode = Schema.AccessMode.WRITE_ONLY)) } ) PetSimple pet) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SiblingsResourceResponse.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.siblings.PetSimple; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/test") public class SiblingsResourceResponse { @GET @Operation( responses = { @ApiResponse( responseCode = "300", description = "aaa", useReturnTypeSchema = true, content = { @Content( mediaType = "application/json", schema = @Schema( description = "resource pet", accessMode = Schema.AccessMode.READ_ONLY)), @Content( mediaType = "application/xml", schema = @Schema( description = "resource pet xml", accessMode = Schema.AccessMode.READ_ONLY)) })}) public PetSimple getCart() { return null; } @Path("/impl") @GET @Operation( responses = { @ApiResponse( responseCode = "300", description = "aaa", content = { @Content( mediaType = "application/json", schema = @Schema( description = "resource pet", implementation = PetSimple.class, accessMode = Schema.AccessMode.READ_ONLY)), @Content( mediaType = "application/xml", schema = @Schema( description = "resource pet xml", implementation = PetSimple.class, accessMode = Schema.AccessMode.READ_ONLY)) })}) public PetSimple getCartImpl() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SiblingsResourceSimple.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.siblings.PetSimple; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/test") public class SiblingsResourceSimple { @GET @Operation( responses = { @ApiResponse( responseCode = "300", description = "aaa", useReturnTypeSchema = true, content = { @Content( mediaType = "*/*", schema = @Schema( description = "resource pet", accessMode = Schema.AccessMode.READ_ONLY)) })}) public PetSimple getCart() { return null; } @Path("/impl") @GET @Operation( responses = { @ApiResponse( responseCode = "300", description = "aaa", content = { @Content( mediaType = "*/*", schema = @Schema( description = "resource pet", implementation = PetSimple.class, accessMode = Schema.AccessMode.READ_ONLY)) })}) public PetSimple getCartImpl() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SimpleCallbackResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class SimpleCallbackResource { @Path("/test") @POST @Callback( callbackUrlExpression = "http://$request.query.url", name = "subscription", operation = { @Operation( method = "post", description = "payload data will be sent", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY )) }, responses = { @ApiResponse( responseCode = "200", description = "Return this code if the callback was received and processed successfully" ), @ApiResponse( responseCode = "205", description = "Return this code to unsubscribe from future data updates" ), @ApiResponse( responseCode = "default", description = "All other response codes will disable this callback subscription" ) }), @Operation( method = "get", description = "payload data will be received" ), @Operation( method = "put", description = "payload data will be sent" )}) @Operation(description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads") public SubscriptionResponse subscribe(@Schema(required = true, description = "the authentication token " + "provided after initially authenticating to the application") @HeaderParam("x-auth-token") String token, @Schema(required = true, description = "the URL to call with response " + "data") @QueryParam("url") String url) { return null; } static class SubscriptionResponse { private String subscriptionUuid; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SimpleExamplesResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.petstore.example.SubscriptionResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.POST; import javax.ws.rs.Path; /** * Examples Resource Scenario */ public class SimpleExamplesResource { @Path("/example") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(name = "Schema", description = "Schema", example = "Subscription example"), style = ParameterStyle.SIMPLE, example = "example", examples = { @ExampleObject(name = "subscriptionId_1", value = "12345", summary = "Subscription number 12345", externalValue = "Subscription external value 1") }) }) public SubscriptionResponse subscribe(final int subscriptionId) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SimpleMethods.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class SimpleMethods { @GET @Path("/object") public TestBean getTestBean() { return new TestBean(); } @GET @Path("/int") public int getInt() { return 0; } @GET @Path("/intArray") public int[] getIntArray() { return new int[]{0}; } @GET @Path("/string") public String[] getStringArray() { return new String[]{}; } @GET @Path("/stringArray") public void getWithIntArrayInput(@QueryParam("ids") int[] inputs) { } static class TestBean { public String foo; public TestChild testChild; } static class TestChild { public String foo; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SimpleParameterResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class SimpleParameterResource { @GET @Path("/") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with a payload complex input object", operationId = "sendPayload", deprecated = true ) public void sendPayload(@Parameter(description = "Id Description", required = true, example = "1") @QueryParam("id") final int id) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SimpleRequestBodyResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.GET; import javax.ws.rs.Path; public class SimpleRequestBodyResource { @GET @Path("/") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with a payload complex input object", operationId = "sendPayload", deprecated = true, requestBody = @RequestBody(description = "Test RequestBody") ) public void sendPayload(final User user) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SimpleResourceWithVendorAnnotation.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.NotFoundModel; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Path("/") @Produces({ "application/xml" }) public class SimpleResourceWithVendorAnnotation { @VendorFunnyAnnotation @GET @Path("/{id}") @ApiResponses({ @ApiResponse( responseCode = "400", description = "Invalid ID", content = @Content( mediaType = "*/*", schema = @Schema(implementation = NotFoundModel.class) ) ), @ApiResponse(responseCode = "404", description = "object not found") }) public Response getTest( @PathParam("id") final String id, @QueryParam("limit") final Integer limit) throws WebApplicationException { return Response.ok().build(); } @GET @Path("/{id}/value") @Produces({ "text/plain" }) @ApiResponses({ @ApiResponse( responseCode = "400", description = "Invalid ID", content = @Content( mediaType = "*/*", schema = @Schema(implementation = NotFoundModel.class) ) ), @ApiResponse(responseCode = "404", description = "object not found") }) public Response getStringValue() throws WebApplicationException { return Response.ok().entity("ok").build(); } /** * Annotation processed by some vendor libraries. It could be used by swagger because the result of that processing * could return with rest error response. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public static @interface VendorFunnyAnnotation { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SimpleResponsesResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class SimpleResponsesResource { @GET @Path("/") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output object", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = @Content( mediaType = "application/json", schema = @Schema(implementation = SampleResponseSchema.class) ) ), @ApiResponse( description = "boo", content = @Content( mediaType = "*/*", schema = @Schema(implementation = GenericError.class) ) ) } ) public void getResponses() { } static class SampleResponseSchema { @Schema(description = "the user id") private String id; } static class GenericError { private int code; private String message; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SimpleUserResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.data.UserData; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; @Path("/user") @Produces({"application/json", "application/xml"}) @Consumes({"application/json", "application/xml"}) public class SimpleUserResource { static UserData userData = new UserData(); @POST @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response createUser( @Parameter(description = "Created user object", required = true) User user) { userData.addUser(user); return Response.ok().entity("").build(); } @POST @Path("/createUserWithReturnType") @Operation(summary = "Create user with return type", description = "This can only be done by the logged in user.") public User createUserWithReturnType( @Parameter(description = "Created user object", required = true) User user) { userData.addUser(user); return null; } @POST @Path("/createUserWithResponseAnnotation") @Operation(summary = "Create user with response annotation", description = "This can only be done by the logged in user.") @ApiResponse(description = "aaa", responseCode = "200", content = {@Content(schema = @Schema(implementation = User.class))}) public User createUserWithResponseAnnotation( @Parameter(description = "Created user object", required = true) User user) { userData.addUser(user); return null; } @POST @Path("/createUserWithReturnTypeAndResponseAnnotation") @Operation(summary = "Create user with return type and response annotation", description = "This can only be done by the logged in user.") @ApiResponse(description = "aaa", responseCode = "200") public User createUserWithReturnTypeAndResponseAnnotation( @Parameter(description = "Created user object", required = true) User user) { userData.addUser(user); return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SingleExampleResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; public class SingleExampleResource { @POST @Path("/test1") public Response test1( @RequestBody( content = @Content( mediaType = "application/json", examples = @ExampleObject(value = "{\"foo\" : \"foo\", \"bar\" : \"bar\"}") ) ) final User user) { return Response.ok().entity("").build(); } @POST @Path("/test2") @Operation(requestBody = @RequestBody( content = @Content( mediaType = "application/json", schema = @Schema(implementation = User.class), examples = @ExampleObject(value = "{\"foo\" : \"foo\", \"bar\" : \"bar\"}") ) )) public Response test2(final User user) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SubResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; public class SubResource { @GET @Operation(description = "gets an object by ID", tags = "Employees") @ApiResponse(description = "200", responseCode = "200", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Pet.class)))) public void getAllEmployees() { return; } @Operation(description = "gets an object by ID", tags = "Employees") @ApiResponse(description = "200", responseCode = "200", content = @Content(schema = @Schema(implementation = Pet.class))) @GET @Path("{id}") public Pet getSubresourceOperation(@PathParam("id") Long userId) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SubResourceHead.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.Path; @Path("/head") public class SubResourceHead { /** * This path is expected to be collected * * @return class instance of sub-resource */ @Path("tail") public Class getTail() { return SubResourceTail.class; } /** * This path is expected to be collected * * @return class instance of sub-resource */ @Path("noPath") public Class getNoPath() { return NoPathSubResource.class; } /** * This path is expected to be skipped as {@link String} doesn't process * any requests. * * @return string class */ @Path("stringClass") public Class getStringClass() { return String.class; } /** * This path is expected to be skipped as resource class is unknown here. * * @return {@code null} */ @Path("anyClass") public Class getAnyClass() { return null; } /** * This path is expected to be skipped as resource class is unknown here. * * @return {@code null} */ @Path("wildcardClass") public Class getWildcardClass() { return null; } /** * This path is expected to be skipped as method result is an array. * * @return {@code null} */ @Path("classes") public Class[] getClasses() { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/SubResourceTail.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; public class SubResourceTail { @Operation(description = "Returns greeting") @GET @Path("/hello") public String getGreeting() { return "Hello!"; } @Operation(description = "Echoes passed string") @GET @Path("{string}") public String getEcho(@PathParam("string") String string) { return string; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/TagsResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @OpenAPIDefinition(tags = { @Tag(name = "Definition First Tag"), @Tag(name = "Definition Second Tag full", description = "desc definition") }) @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Fifth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Sixth Tag") public class TagsResource { @GET @Path("/") @Operation(tags = {"Example Tag", "Second Tag"}) @Tag(name = "Third Tag") @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc", externalDocs = @ExternalDocumentation(description = "docs desc")) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Test2607.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.info.Info; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @OpenAPIDefinition(info = @Info( title = "TEST", version = "0.0", description = "Test API" ) ) @Path("/swaggertest/") public class Test2607 { @GET @Path("name") @Produces(MediaType.TEXT_PLAIN) public String getName() { return "SwaggerTest"; } @Path("subresource") @Operation public TestSub2607 getSubResource() { return new TestSub2607(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/TestResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; @Path("test") @Produces(MediaType.APPLICATION_JSON) public class TestResource { @Path("/status") @GET @Operation(description = "Get status") public String getStatus() { return "{\"status\":\"OK!\"}"; } @Path("/more") @Operation(description = "Get more") @Produces({MediaType.APPLICATION_XML}) public TestSubResource getSubResource( @QueryParam("qp") Integer qp) { return new TestSubResource(); } @Path("/evenmore") @Operation(description = "Get even more") @Produces({MediaType.APPLICATION_XML}) @Consumes(MediaType.APPLICATION_JSON) public TestSubResource getEvenMoreSubResource(Pet pet) { return new TestSubResource(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/TestSub2607.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Produces(MediaType.APPLICATION_JSON) public class TestSub2607 { @GET @Path("version") @Produces(MediaType.TEXT_PLAIN) public String getSubResourceVersion() { return "1.0.0"; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/TestSubResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Produces(MediaType.APPLICATION_JSON) public class TestSubResource { @Path("/otherStatus") @GET @Operation(description = "Get the other status!") public String otherStatus() { return "{\"a\":\"Still Ok!\"}"; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket2340Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("/test") public class Ticket2340Resource { @Produces({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON }) @Path("/test") @POST public String getAnimal(Animal animal) { return "ok"; } @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")//, visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"), @JsonSubTypes.Type(value = Cat.class, name = "cat") }) public static class Animal { } @JsonTypeName("dog") public static class Dog extends Animal { public double barkVolume; } @JsonTypeName("cat") public static class Cat extends Animal { boolean likesCream; public int lives; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket2644AnnotatedInterface.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @Path("resources") @Tag(name = "resource") public interface Ticket2644AnnotatedInterface { @GET Response getResource(); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket2644ConcreteImplementation.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.core.Response; public class Ticket2644ConcreteImplementation implements Ticket2644AnnotatedInterface { public Response getResource() { // Get the resource return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket2763Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; public class Ticket2763Resource { @GET @Path("/array") @ApiResponse(content = @Content( mediaType = MediaType.APPLICATION_JSON, array = @ArraySchema(schema = @Schema( ref="https://openebench.bsc.es/monitor/tool/tool.json")))) public void getArrayResponses() { } @GET @Path("/schema") @ApiResponse(content = @Content( mediaType = MediaType.APPLICATION_JSON, schema = @Schema(ref="https://openebench.bsc.es/monitor/tool/tool.json"))) public void getSchemaResponses() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket2793Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.Map; import java.util.UUID; @OpenAPIDefinition @Path("distances") public interface Ticket2793Resource { @GET @Produces(MediaType.APPLICATION_JSON) @ApiResponses({ @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = DistancesResponse.class))) }) Response getDistances(); abstract class DistancesResponse implements Map> { } public static class RouteMetric { public String foo; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket2794Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.validation.constraints.NotNull; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.Arrays; @Path("/notnullparameter") public class Ticket2794Resource { @Produces({ MediaType.APPLICATION_JSON }) @GET public Response getBooks( @QueryParam("page") @NotNull int page) { return Response.ok( Arrays.asList( new Book(), new Book() ) ).build(); } @Path("/new_reqBody_required") @POST public Response insert(@RequestBody(required = true) Book book) { return Response.ok().build(); } @Path("/newnotnull") @POST public Response insertnotnull(@NotNull Book book) { return Response.ok().build(); } public static class Book { public String foo; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket2806Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; public class Ticket2806Resource { @GET @Path("/test") public Test getTest() { return null; } class Test { private String[] stringArray; @ArraySchema( minItems = 2, maxItems = 4, uniqueItems = true, arraySchema = @Schema( description = "Array desc", example = "[\"aaa\", \"bbb\"]" ), schema = @Schema( description = "Hello, World!", example = "Lorem ipsum dolor set" ) ) public void setStringArray(String[] value) { stringArray = value; } public String[] getStringArray() { return stringArray; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket2818Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("/bookstore") public class Ticket2818Resource { @Produces({ MediaType.APPLICATION_JSON }) @Path("/{id}") @GET public Book getBook( @Parameter( in = ParameterIn.PATH, schema = @Schema ( type = "integer", format = "int32" ) ) @PathParam("id") int id) { return new Book(); } public static class Book { public String foo; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket2848Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.List; @Path("/") public class Ticket2848Resource { @GET public Town getter() { return null; } public static class Town { @ArraySchema( schema = @Schema(required = true), minItems = 1,uniqueItems = true ) public List streets; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket3015Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.net.URI; @Path("test") public class Ticket3015Resource { @Operation(responses = { @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = URI.class))), @ApiResponse(responseCode = "400", description = "Bad Request"), @ApiResponse(responseCode = "500", description = "Internal Server Error") }) @GET @Path("/test") public void schemaImpl() { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket3587Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.ExampleObject; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("test") public class Ticket3587Resource { @GET @Path("/test") public void parameterExamplesOrderingTest( @Parameter( in = ParameterIn.QUERY, examples = { @ExampleObject( name = "Example One" ), @ExampleObject( name = "Example Two" ), @ExampleObject( name = "Example Three" ) } ) String parameterWithOrderedExamples, @Parameter( in = ParameterIn.QUERY, examples = { @ExampleObject( name = "Example Three" ), @ExampleObject( name = "Example Two" ), @ExampleObject( name = "Example One" ) } ) String parameterWithExamplesInDifferentOrder) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket3731BisResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import java.util.List; @Path("/test") public class Ticket3731BisResource { @GET @Path("/cart") @Operation( summary = "Get cart items", description = "Paging follows RFC 5005.") public List getCart( @QueryParam("pageSize") @DefaultValue("50") @Parameter(description = "Number of items per page. Range[1, 200]") // @Min(2) @Max(202) @Schema(minimum = "1", maximum = "200") final int pageSize) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket3731Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import java.util.List; @Path("/test") public class Ticket3731Resource { @GET @Path("/cart") @Operation( summary = "Get cart items", description = "Paging follows RFC 5005.") public List getCart( @QueryParam("pageSize") @DefaultValue("50") @Min(1) @Max(200) @Parameter(description = "Number of items per page. Range[1, 200]") // final int pageSize) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4065Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Path("/bar") public class Ticket4065Resource { @GET @Path("") @Produces({"application/json"}) public void test( @Parameter(in = ParameterIn.QUERY, name = "blub", explode = Explode.FALSE) Long[] ids ) {} } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4341Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotNull; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.List; public class Ticket4341Resource { @GET @Path("/user") public User getUsers() { return null; } static class User { @ArraySchema( arraySchema = @Schema(requiredMode = Schema.RequiredMode.REQUIRED), schema = @Schema(type = "string") ) public List requiredArray; @ArraySchema( arraySchema = @Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED), schema = @Schema(type = "string") ) public List notRequiredArray; @ArraySchema( arraySchema = @Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED), schema = @Schema(type = "string") ) @NotNull public List notRequiredArrayWithNotNull; @ArraySchema( arraySchema = @Schema(requiredMode = Schema.RequiredMode.AUTO), schema = @Schema(type = "string") ) @NotNull public List autoRequiredWithNotNull; @ArraySchema( arraySchema = @Schema(requiredMode = Schema.RequiredMode.AUTO), schema = @Schema(type = "string") ) public List autoNotRequired; @ArraySchema( arraySchema = @Schema(requiredMode = Schema.RequiredMode.REQUIRED) ) public List requiredArrayArraySchemaOnly; @ArraySchema( schema = @Schema(type = "string", requiredMode = Schema.RequiredMode.REQUIRED) ) public List requiredItemsOnlyArray; @ArraySchema( arraySchema = @Schema( description = "array-level description", deprecated = true, accessMode = Schema.AccessMode.READ_ONLY ), schema = @Schema( description = "item-level description", deprecated = false, accessMode = Schema.AccessMode.WRITE_ONLY, format = "email" ) ) public List metadataArray; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4412Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import java.util.List; @Path("/test") public class Ticket4412Resource { @Path("/sws/{var:.*}") @GET @Produces(MediaType.TEXT_XML) public List getCart(@PathParam("var") String var) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4446Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.List; @Path("/test") public class Ticket4446Resource { @Path("test") @GET public MyPojo getCart() { return null; } public static class MyPojo { public List someStrings; public List morePojos; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4483Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import java.util.Map; /* */ @Tag( name = "Dummy", description = "Dummy resource for testing setup" ) @Path("test") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) @ApiResponses({ @ApiResponse(responseCode = "401", description = "Authentication is required", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Ticket4483Resource.LocalizedError.class)))) }) public class Ticket4483Resource { @GET @Operation( description = "Dummy GET" ) @ApiResponse(responseCode = "200", description = "test", useReturnTypeSchema = true) public Map dummy() { Map map = new java.util.HashMap(); map.put("success", Boolean.TRUE); return map; } @Path("/opresp") @GET @Operation( responses = { @ApiResponse(responseCode = "200", description = "Dummy GET opresp", useReturnTypeSchema = true)}) public Map dummyopresp() { Map map = new java.util.HashMap(); map.put("success", Boolean.TRUE); return map; } @Path("/oprespnodesc") @GET @Operation( responses = { @ApiResponse(responseCode = "200", useReturnTypeSchema = true)}) public Map oprespnodesc() { Map map = new java.util.HashMap(); map.put("success", Boolean.TRUE); return map; } public static class LocalizedError { public String code; public String message; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4804CustomClass.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Min; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import java.math.BigDecimal; public class Ticket4804CustomClass { public static interface ValidationGroup { } public static interface OtherValidationGroup { } @NotNull public String nonGroupValidatedField; @Min(value = 1, groups = ValidationGroup.class) public Integer singleGroupValidatedField; @DecimalMin(value = "1.0", groups = {ValidationGroup.class, OtherValidationGroup.class}) public BigDecimal multipleGroupValidatedField; @Pattern(regexp = ".*", groups = OtherValidationGroup.class) public String otherGroupValidatedField; @NotEmpty(groups = ValidationGroup.class) public String singleGroupValidatedField2; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4804NotBlankResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.parameters.ValidatedParameter; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; @Path("/test") public class Ticket4804NotBlankResource { @POST @Path("/createcart") public void postCart(@Valid @ValidatedParameter(onCreate.class) Cart cart) {} @PUT @Path("/updatecart") public void putCart(@Valid @ValidatedParameter(onUpdate.class) Cart cart) {} @PUT @Path("/barcart") public void barCart(Cart cart) {} public static interface onCreate {} public static interface onUpdate {} public static class CartDetails { @NotBlank(groups = {onCreate.class, onUpdate.class}) public String name; @NotEmpty public String[] description; } public static class Cart { @NotBlank(groups = {onCreate.class, onUpdate.class}) public int[] pageSizes; @NotNull public CartDetails notNullcartDetails; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4804ProcessorResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.core.util.ValidatorProcessor; import io.swagger.v3.oas.annotations.parameters.ValidatedParameter; import io.swagger.v3.oas.models.media.Schema; import javax.validation.Valid; import javax.validation.constraints.NotNull; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @Path("/test") public class Ticket4804ProcessorResource { @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) static @interface MyValidatorInterface { Class[] groups() default {}; } public static class CustomValidatorProcessor implements ValidatorProcessor { @Override public boolean applyBeanValidatorAnnotations(Schema property, Annotation[] annotations, Schema parent, boolean applyNotNullAnnotations) { if (annotations == null || annotations.length < 1) { return false; } Map annos = new HashMap<>(); if (annotations != null) { for (Annotation anno : annotations) { annos.put(anno.annotationType().getName(), anno); } } if (annos.containsKey(MyValidatorInterface.class.getName()) && annos.containsKey(NotNull.class.getName())) { MyValidatorInterface myValid = (MyValidatorInterface) annos.get(MyValidatorInterface.class.getName()); NotNull notNull = (NotNull) annos.get(NotNull.class.getName()); for (Class group : notNull.groups()) { if (Arrays.stream(myValid.groups()).anyMatch(t -> t.equals(group))) { parent.addRequiredItem(property.getName()); return true; } } } return false; } @Override public Set resolveInvocationGroups(Map annos) { if (annos.containsKey(MyValidatorInterface.class.getName())) { MyValidatorInterface myValid = (MyValidatorInterface) annos.get(MyValidatorInterface.class.getName()); return new HashSet<>(Arrays.asList(myValid.groups())); } return null; } @Override public Set resolveInvocationAnnotations(Annotation[] annotations) { for (Annotation annotation : annotations) { if (annotation.annotationType().equals(MyValidatorInterface.class)) { return Collections.singleton(annotation); } } return null; } } @PUT @Path("/updatecart") public void putCart(@Valid @MyValidatorInterface(groups = {onFoo.class}) @ValidatedParameter(onUpdate.class) Cart cart) {} @POST @Path("/createcart") public void postCart(@Valid @ValidatedParameter(onCreate.class) Cart cart) {} @PUT @Path("/foocart") public void fooCart(@Valid @ValidatedParameter(onFoo.class) Cart cart) {} @PUT @Path("/barcart") public void barCart(Cart cart) {} public static interface onCreate {} public static interface onUpdate {} public static interface onFoo {} public static class CartDetails { @NotNull(groups = {onCreate.class}) public String name; @NotNull public String description; } public static class Cart { @NotNull(groups = {onCreate.class}) public int pageSize; @NotNull(groups = {onFoo.class}) public CartDetails cartDetails; @NotNull public CartDetails notNullcartDetails; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4804Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.parameters.ValidatedParameter; import javax.validation.Valid; import javax.validation.constraints.NotNull; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; @Path("/test") public class Ticket4804Resource { @POST @Path("/createcart") public void postCart(@Valid @ValidatedParameter(onCreate.class) Cart cart) {} @PUT @Path("/updatecart") public void putCart(@Valid @ValidatedParameter(onUpdate.class) Cart cart) {} @PUT @Path("/foocart") public void fooCart(@Valid @ValidatedParameter(onFoo.class) Cart cart) {} @PUT @Path("/barcart") public void barCart(Cart cart) {} public static interface onCreate {} public static interface onUpdate {} public static interface onFoo {} public static class CartDetails { @NotNull(groups = {onCreate.class}) public String name; @NotNull public String description; } public static class Cart { @NotNull(groups = {onCreate.class}) public int pageSize; @NotNull(groups = {onFoo.class}) public CartDetails cartDetails; @NotNull public CartDetails notNullcartDetails; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4850Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/bar") public class Ticket4850Resource { @GET @Path("") public ExtensionsResource test( ) {return new ExtensionsResource();} @Schema( description = "ExtensionsResource", extensions = { @Extension(name = "x-user", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "user-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) private class ExtensionsResource { public ExtensionsResource() {} } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4859Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.PUT; import javax.ws.rs.Path; @Path("/test") public class Ticket4859Resource { @PUT @Path("/minlength") public void minlength(Minlength minlength) {} public static class Minlength { @Schema(example = "4242424242424242", minLength = 12, maxLength = 19, required = true) public String name; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4878Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @Path("{globalPathParam}") public class Ticket4878Resource { public Ticket4878Resource(@PathParam("globalPathParam") @Schema($comment="3.1 property for global path param") String globalPathParam) {} @GET @Path("{localPathParam}") public void getMethod(@PathParam("localPathParam") @Schema($comment="3.1 property for local path param") String localPathParam) {} } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket4879Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.Size; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import java.util.List; @Path("/test") public class Ticket4879Resource { @PUT @Path("/test") public void test(DefaultClass defaultClass) {} @GET @Path("/testDefaultValueAnnotation") public void testDefault( @DefaultValue(value = "true") @QueryParam(value = "myBool") Boolean myBool, @DefaultValue(value = "1") @QueryParam(value = "myInt") Integer myInt) { } @GET @Path("/testsize") public void testSize(@Size(min = 1, max = 100) List myList) {} public static class DefaultClass { @Schema(defaultValue = "true") public Boolean name; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/Ticket5017Resource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.Map; @Path("/test") public class Ticket5017Resource { @GET public void myMethod(Example request) {} public static class Example { @Schema(propertyNames = MyEnum.class) private Map myMap; public Map getMyMap() { return myMap; } public void setMyMap(Map myMap) { this.myMap = myMap; } } public enum MyEnum { FOO, BAR } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/UploadRequest.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.media.Schema; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; import java.io.InputStream; @Schema(name = "UploadRequest", title="Schema for Upload") public class UploadRequest { @Hidden @FormDataParam("picture") private FormDataContentDisposition disposition; public FormDataContentDisposition getDisposition() { return disposition; } public void setDisposition(FormDataContentDisposition disposition) { this.disposition = disposition; } @FormDataParam("name") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Schema(name="picture", type="string", format="binary") @FormDataParam("picture") private InputStream upload; public InputStream getUpload() { return upload; } public void setUpload(InputStream upload) { this.upload = upload; } @Override public String toString() { final String NL = System.lineSeparator(); StringBuilder sb = new StringBuilder(); sb.append(super.toString()); sb.append("name: ").append(name).append(NL); return sb.toString(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/UploadResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @Path("/upload") public class UploadResource { @POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) public Response uploadWithBean(@BeanParam UploadRequest personData) { return Response.ok().build(); } @Path("/requestbody") @POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) @RequestBody(content = @Content(schema = @Schema(implementation = UploadRequest.class))) public Response uploadWithBeanAndRequestBody(@BeanParam UploadRequest personData) { return Response.ok().build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/UrlEncodedResourceWithEncodings.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.List; import static io.swagger.v3.oas.annotations.enums.Explode.FALSE; import static io.swagger.v3.oas.annotations.enums.Explode.TRUE; @Path("/things") @Produces("application/json") public class UrlEncodedResourceWithEncodings { @POST @Path("/search") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response searchForThings( @BeanParam CompositeFormBody body ) { return Response.status(200).entity("Searching for something").build(); } @POST @Path("/sriracha") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response srirachaThing( @Parameter(name = "id", style = ParameterStyle.FORM, explode = TRUE, description = "id param") @FormParam( "id" ) List ids, @Parameter(name = "name", style = ParameterStyle.FORM, explode = FALSE) @FormParam( "name" ) List names) { return Response.status(200).entity("Sriracha!").build(); } public static class CompositeFormBody { @Parameter(name = "id", style = ParameterStyle.FORM, explode = TRUE, description = "id param") @FormParam("id") public List ids; @Parameter(name = "name", style = ParameterStyle.FORM, explode = FALSE) @FormParam("name") public List names; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/UserAnnotation.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.oas.annotations.Operation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) @Operation(tags = {"test"}) public @interface UserAnnotation { /** * The identifying name of the contact person/organization. * * @return the name of the contact **/ String name() default ""; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/UserAnnotationResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import javax.validation.constraints.NotNull; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("test") @Produces(MediaType.APPLICATION_JSON) public class UserAnnotationResource { @Path("/status") @GET @UserAnnotation(name = "test") @NotNull public String getStatus() { return "{\"status\":\"OK!\"}"; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/UserResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.data.UserData; import io.swagger.v3.jaxrs2.resources.exception.ApiException; import io.swagger.v3.jaxrs2.resources.exception.NotFoundException; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; @Path("/user") @Produces({"application/json", "application/xml"}) public class UserResource { static UserData userData = new UserData(); @POST @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response createUser( @Parameter(description = "Created user object", required = true) User user) { userData.addUser(user); return Response.ok().entity("").build(); } @POST @Path("/createWithArray") @Operation(summary = "Creates list of users with given input array") public Response createUsersWithArrayInput(@Parameter(description = "List of user object", required = true) User[] users) { for (User user : users) { userData.addUser(user); } return Response.ok().entity("").build(); } @POST @Path("/createWithList") @Operation(summary = "Creates list of users with given input array") public Response createUsersWithListInput(@Parameter(description = "List of user object", required = true) java.util.List users) { for (User user : users) { userData.addUser(user); } return Response.ok().entity("").build(); } @PUT @Path("/{username}") @Operation(summary = "Updated user", description = "This can only be done by the logged in user.", responses = { @ApiResponse(responseCode = "200", description = "user updated"), @ApiResponse(responseCode = "400", description = "Invalid user supplied"), @ApiResponse(responseCode = "404", description = "User not found")}) public Response updateUser( @Parameter(description = "name that need to be deleted", required = true, examples = { @ExampleObject(name = "example1", value = "example1", summary = "Summary example 1", externalValue = "external value 1"), @ExampleObject(name = "example2", value = "example2", summary = "Summary example 2", externalValue = "external value 2") }) @PathParam("username") String username, @Parameter(description = "Updated user object", required = true) User user) { userData.addUser(user); return Response.ok().entity("").build(); } @DELETE @Path("/{username}") @Operation(summary = "Delete user", description = "This can only be done by the logged in user.", responses = { @ApiResponse(responseCode = "200", description = "user deteled"), @ApiResponse(responseCode = "400", description = "Invalid username supplied"), @ApiResponse(responseCode = "404", description = "User not found")}) public Response deleteUser( @Parameter(description = "The name that needs to be deleted", required = true) @PathParam("username") String username) { if (userData.removeUser(username)) { return Response.ok().entity("").build(); } else { return Response.status(Response.Status.NOT_FOUND).build(); } } @GET @Path("/{username}") @Operation(summary = "Get user by user name", responses = { @ApiResponse(description = "The user", content = @Content(mediaType = "application/json", schema = @Schema(implementation = User.class))), @ApiResponse(responseCode = "400", description = "Invalid username supplied"), @ApiResponse(responseCode = "400", description = "User not found")}) public Response getUserByName( @Parameter(description = "The name that needs to be fetched. Use user1 for testing. ", required = true) @PathParam("username") String username) throws ApiException { User user = userData.findUserByName(username); if (null != user) { return Response.ok().entity(user).build(); } else { throw new NotFoundException(404, "User not found"); } } @GET @Path("/login") @Operation(summary = "Logs user into the system", responses = { @ApiResponse(description = "Successfully logged in", content = @Content(schema = @Schema(implementation = String.class))), @ApiResponse(responseCode = "400", description = "Invalid username/password supplied")}) public Response loginUser( @Parameter(description = "The user name for login", required = true) @QueryParam("username") String username, @Parameter(description = "The password for login in clear text", required = true) @QueryParam("password") String password) { return Response.ok() .entity("logged in user session:" + System.currentTimeMillis()) .build(); } @GET @Path("/logout") @Operation(summary = "Logs out current logged in user session") public Response logoutUser() { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/WebHookResource.java ================================================ package io.swagger.v3.jaxrs2.resources; import io.swagger.v3.jaxrs2.resources.siblings.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Webhook; import io.swagger.v3.oas.annotations.Webhooks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; @Webhooks({ @Webhook( name = "newPet", operation = @Operation( requestBody = @RequestBody( description = "Information about a new pet in the system", content = { @Content( mediaType = "application/json", schema = @Schema( description = "Webhook Pet", implementation = Pet.class ) ) } ), method = "post", responses = @ApiResponse( responseCode = "200", description = "Return a 200 status to indicate that the data was received successfully" ) ) ) }) public class WebHookResource { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/data/PetData.java ================================================ package io.swagger.v3.jaxrs2.resources.data; import io.swagger.v3.jaxrs2.resources.model.Category; import io.swagger.v3.jaxrs2.resources.model.Pet; import io.swagger.v3.jaxrs2.resources.model.Tag; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class PetData { static List pets = new ArrayList(); static List categories = new ArrayList(); static { categories.add(createCategory(1, "Dogs")); categories.add(createCategory(2, "Cats")); categories.add(createCategory(3, "Rabbits")); categories.add(createCategory(4, "Lions")); pets.add(createPet(1, categories.get(1), "Cat 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(2, categories.get(1), "Cat 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "available")); pets.add(createPet(3, categories.get(1), "Cat 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "pending")); pets.add(createPet(4, categories.get(0), "Dog 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(5, categories.get(0), "Dog 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "sold")); pets.add(createPet(6, categories.get(0), "Dog 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "pending")); pets.add(createPet(7, categories.get(3), "Lion 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(8, categories.get(3), "Lion 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "available")); pets.add(createPet(9, categories.get(3), "Lion 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "available")); pets.add(createPet(10, categories.get(2), "Rabbit 1", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "available")); } public Pet getPetById(long petId) { for (Pet pet : pets) { if (pet.getId() == petId) { return pet; } } return null; } public List findPetByStatus(String status) { String[] statues = status.split(","); List result = new ArrayList(); for (Pet pet : pets) { for (String s : statues) { if (s.equals(pet.getStatus())) { result.add(pet); } } } return result; } public List findPetByCategory(Category category) { return pets.stream().filter(pet -> category.equals(pet.getCategory())).collect(Collectors.toList()); } public List findPetByTags(String tags) { String[] tagList = tags.split(","); List result = new ArrayList(); for (Pet pet : pets) { if (null != pet.getTags()) { for (Tag tag : pet.getTags()) { for (String tagListString : tagList) { if (tagListString.equals(tag.getName())) { result.add(pet); } } } } } return result; } public void addPet(Pet pet) { if (pets.size() > 0) { for (int i = pets.size() - 1; i >= 0; i--) { if (pets.get(i).getId() == pet.getId()) { pets.remove(i); } } } pets.add(pet); } static Pet createPet(long id, Category cat, String name, String[] urls, String[] tags, String status) { Pet pet = new Pet(); pet.setId(id); pet.setCategory(cat); pet.setName(name); if (null != urls) { List urlObjs = new ArrayList(); for (String urlString : urls) { urlObjs.add(urlString); } pet.setPhotoUrls(urlObjs); } List tagObjs = new ArrayList(); int i = 0; if (null != tags) { for (String tagString : tags) { i = i + 1; Tag tag = new Tag(); tag.setId(i); tag.setName(tagString); tagObjs.add(tag); } } pet.setTags(tagObjs); pet.setStatus(status); return pet; } static Category createCategory(long id, String name) { Category category = new Category(); category.setId(id); category.setName(name); return category; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/data/UserData.java ================================================ package io.swagger.v3.jaxrs2.resources.data; import io.swagger.v3.jaxrs2.resources.model.User; import java.util.ArrayList; import java.util.List; public class UserData { static List users = new ArrayList(); static { users.add(createUser(1, "user1", "first name 1", "last name 1", "email1@test.com", "123-456-7890", 1)); users.add(createUser(2, "user2", "first name 2", "last name 2", "email2@test.com", "123-456-7890", 2)); users.add(createUser(3, "user3", "first name 3", "last name 3", "email3@test.com", "123-456-7890", 3)); users.add(createUser(4, "user4", "first name 4", "last name 4", "email4@test.com", "123-456-7890", 1)); users.add(createUser(5, "user5", "first name 5", "last name 5", "email5@test.com", "123-456-7890", 2)); users.add(createUser(6, "user6", "first name 6", "last name 6", "email6@test.com", "123-456-7890", 3)); users.add(createUser(7, "user7", "first name 7", "last name 7", "email7@test.com", "123-456-7890", 1)); users.add(createUser(8, "user8", "first name 8", "last name 8", "email8@test.com", "123-456-7890", 2)); users.add(createUser(9, "user9", "first name 9", "last name 9", "email9@test.com", "123-456-7890", 3)); users.add(createUser(10, "user10", "first name 10", "last name 10", "email10@test.com", "123-456-7890", 1)); users.add(createUser(11, "user?10", "first name ?10", "last name ?10", "email101@test.com", "123-456-7890", 1)); } public User findUserByName(String username) { for (User user : users) { if (user.getUsername().equals(username)) { return user; } } return null; } public void addUser(User user) { if (users.size() > 0) { for (int i = users.size() - 1; i >= 0; i--) { if (users.get(i).getUsername().equals(user.getUsername())) { users.remove(i); } } } users.add(user); } public boolean removeUser(String username) { if (users.size() > 0) { for (int i = users.size() - 1; i >= 0; i--) { if (users.get(i).getUsername().equals(username)) { users.remove(i); return true; } } } return false; } private static User createUser(long id, String username, String firstName, String lastName, String email, String phone, int userStatus) { User user = new User(); user.setId(id); user.setUsername(username); user.setFirstName(firstName); user.setLastName(lastName); user.setEmail(email); user.setPassword("XXXXXXXXXXX"); user.setPhone(phone); user.setUserStatus(userStatus); return user; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/exception/ApiException.java ================================================ package io.swagger.v3.jaxrs2.resources.exception; public class ApiException extends Exception { private int code; public ApiException(int code, String msg) { super(msg); this.code = code; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/exception/NotFoundException.java ================================================ package io.swagger.v3.jaxrs2.resources.exception; public class NotFoundException extends ApiException { private int code; public NotFoundException(int code, String msg) { super(code, msg); this.code = code; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/extensions/ExtensionsResource.java ================================================ package io.swagger.v3.jaxrs2.resources.extensions; import io.swagger.v3.jaxrs2.resources.model.ExtensionUser; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.info.Contact; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Encoding; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.OAuthFlow; import io.swagger.v3.oas.annotations.security.OAuthFlows; import io.swagger.v3.oas.annotations.security.OAuthScope; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityScheme; import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.servers.ServerVariable; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; @OpenAPIDefinition( extensions = { @Extension(name = "x-openapi", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "openapi-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) }, info = @Info( extensions = { @Extension(name = "x-info", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "info-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) }, contact = @Contact( extensions = { @Extension(name = "x-contact", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "contact-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ), license = @License( extensions = { @Extension(name = "x-license", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "license-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) ), servers = @Server( extensions = { @Extension(name = "x-server", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "server-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) }, variables = @ServerVariable( name = "aa", defaultValue = "aa", extensions = { @Extension(name = "x-servervar", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "servervar-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) ), externalDocs = @ExternalDocumentation( extensions = { @Extension(name = "x-externalDocs", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "externalDocs-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) ) @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, description = "myOauthSecurity Description", flows = @OAuthFlows( implicit = @OAuthFlow( authorizationUrl = "http://x.com", scopes = @OAuthScope( name = "write:pets", description = "modify pets in your account" ), extensions = { @Extension(name = "x-oauthflow", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "oauthflow-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ), extensions = { @Extension(name = "x-oauthflows", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "oauthflows-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ), extensions = { @Extension(name = "x-security", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "security-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) @SecurityRequirement(name = "myOauth2Security", scopes = {"write:pets"} ) public class ExtensionsResource { @GET @Path("/") @Tag( name = "MyTag", extensions = { @Extension(name = "x-tag", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "tag-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description", extensions = { @Extension(name = "x-operation", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "x-operation-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}), @Extension(properties = { @ExtensionProperty(name = "codes", value = "[\"11\", \"12\"]", parseValue = true), @ExtensionProperty(name = "name", value = "Josh")}) }) public Response getSummaryAndDescription( @Parameter( extensions = @Extension( name = "x-parameter", properties = { @ExtensionProperty(name = "parameter", value = "value") } ), examples = { @ExampleObject( name = "example1", value = "example1", summary = "Summary example 1", externalValue = "external value 1", extensions = { @Extension(name = "x-examples", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "examples-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) } ) @QueryParam("subscriptionId") String subscriptionId) { return Response.ok().entity("ok").build(); } @GET @Path("/user") @Operation( operationId = "getUser" ) @Callback( callbackUrlExpression = "http://$request.query.url", name = "subscription", extensions = { @Extension(name = "x-callback", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "callback-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) }, operation = { @Operation( method = "post", description = "payload data will be sent", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema( type = "string", format = "uuid", description = "the generated UUID")) }, responses = { @ApiResponse( responseCode = "200", description = "Return this code if the callback was received and processed successfully" ), @ApiResponse( responseCode = "205", description = "Return this code to unsubscribe from future data updates" ), @ApiResponse( responseCode = "default", description = "All other response codes will disable this callback subscription" ) }), @Operation( method = "get", description = "payload data will be received" ), @Operation( method = "put", description = "payload data will be sent" )}) public void getUser( //@Parameter(description = "Parameter with no IN", required = true) @RequestBody( description = "Request Body in Param", content = @Content( mediaType = "application/json", schema = @Schema( extensions = { @Extension(name = "x-schema", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "schema-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ), extensions = { @Extension(name = "x-content", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "content-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) }, encoding = @Encoding( name = "application/xml", extensions = { @Extension(name = "x-encoding", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "encoding-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) ), extensions = { @Extension(name = "x-extension", properties = { @ExtensionProperty(name = "name", value = "param")}), @Extension(name = "x-extension2", properties = { @ExtensionProperty(name = "another", value = "val")})}) ExtensionUser user) { } @POST @Path("/user") @Operation(operationId = "setUser" ) @ApiResponse( description = "200", content = @Content( extensions = { @Extension(name = "x-content", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "content-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) }, encoding = @Encoding( extensions = { @Extension(name = "x-encoding", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "encoding-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) ), links = @Link( name = "aa", description = "aa", operationId = "getUser", extensions = { @Extension(name = "x-links", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "links-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ), extensions = { @Extension(name = "x-response", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "response-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) public ExtensionUser setUser( @Parameter( description = "Parameter with no IN", required = true, schema = @Schema( description = "the user", extensions = { @Extension(name = "x-schema", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "schema-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) ) @RequestBody(description = "Request Body in Param", extensions = { @Extension(name = "x-extension", properties = { @ExtensionProperty(name = "name", value = "param")}), @Extension(name = "x-extension2", properties = { @ExtensionProperty(name = "another", value = "val")})}) ExtensionUser user) { return null; } public static final String YAML = "openapi: 3.0.1\n" + "info:\n" + " contact:\n" + " x-contact:\n" + " name: Josh\n" + " x-contact-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " license:\n" + " x-license:\n" + " name: Josh\n" + " x-license-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-info:\n" + " name: Josh\n" + " x-info-extensions:\n" + " lastName: Hart\n" + " address: House\n" + "externalDocs:\n" + " x-externalDocs:\n" + " name: Josh\n" + " x-externalDocs-extensions:\n" + " lastName: Hart\n" + " address: House\n" + "servers:\n" + "- variables:\n" + " aa:\n" + " default: aa\n" + " x-servervar:\n" + " name: Josh\n" + " x-servervar-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-server-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-server:\n" + " name: Josh\n" + "paths:\n" + " /:\n" + " get:\n" + " tags:\n" + " - MyTag\n" + " summary: Operation Summary\n" + " description: Operation Description\n" + " operationId: operationId\n" + " parameters:\n" + " - name: subscriptionId\n" + " in: query\n" + " schema:\n" + " type: string\n" + " examples:\n" + " example1:\n" + " summary: Summary example 1\n" + " description: example1\n" + " value: example1\n" + " externalValue: external value 1\n" + " x-examples-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-examples:\n" + " name: Josh\n" + " x-parameter:\n" + " parameter: value\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " security:\n" + " - security_key:\n" + " - write:pets\n" + " - read:pets\n" + " - myOauth2Security:\n" + " - write:pets\n" + " x-name: Josh\n" + " x-operation:\n" + " name: Josh\n" + " x-operation-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-codes:\n" + " - \"11\"\n" + " - \"12\"\n" + " /user:\n" + " get:\n" + " operationId: getUser\n" + " requestBody:\n" + " description: Request Body in Param\n" + " content:\n" + " application/json:\n" + " schema:\n" + " type: string\n" + " x-schema:\n" + " name: Josh\n" + " x-schema-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " encoding:\n" + " application/xml:\n" + " x-encoding-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-encoding:\n" + " name: Josh\n" + " x-content:\n" + " name: Josh\n" + " x-content-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-extension:\n" + " name: param\n" + " x-extension2:\n" + " another: val\n" + " responses:\n" + " default:\n" + " description: default response\n" + " content:\n" + " '*/*': {}\n" + " callbacks:\n" + " subscription:\n" + " http://$request.query.url:\n" + " get:\n" + " description: payload data will be received\n" + " put:\n" + " description: payload data will be sent\n" + " post:\n" + " description: payload data will be sent\n" + " parameters:\n" + " - name: subscriptionId\n" + " in: path\n" + " required: true\n" + " schema:\n" + " type: string\n" + " description: the generated UUID\n" + " format: uuid\n" + " responses:\n" + " \"200\":\n" + " description: Return this code if the callback was received and processed\n" + " successfully\n" + " \"205\":\n" + " description: Return this code to unsubscribe from future data updates\n" + " default:\n" + " description: All other response codes will disable this callback\n" + " subscription\n" + " security:\n" + " - security_key:\n" + " - write:pets\n" + " - read:pets\n" + " - myOauth2Security:\n" + " - write:pets\n" + " post:\n" + " operationId: setUser\n" + " requestBody:\n" + " description: Request Body in Param\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/ExtensionUser\"\n" + " x-extension:\n" + " name: param\n" + " x-extension2:\n" + " another: val\n" + " responses:\n" + " default:\n" + " description: \"200\"\n" + " content:\n" + " '*/*':\n" + " schema:\n" + " $ref: \"#/components/schemas/ExtensionUser\"\n" + " x-content:\n" + " name: Josh\n" + " x-content-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " links:\n" + " aa:\n" + " operationId: getUser\n" + " description: aa\n" + " x-links-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-links:\n" + " name: Josh\n" + " x-response-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-response:\n" + " name: Josh\n" + " security:\n" + " - security_key:\n" + " - write:pets\n" + " - read:pets\n" + " - myOauth2Security:\n" + " - write:pets\n" + "components:\n" + " schemas:\n" + " ExtensionUser:\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int64\n" + " username:\n" + " type: string\n" + " firstName:\n" + " type: string\n" + " lastName:\n" + " type: string\n" + " email:\n" + " type: string\n" + " password:\n" + " type: string\n" + " phone:\n" + " type: string\n" + " userStatus:\n" + " type: integer\n" + " description: User Status\n" + " format: int32\n" + " x-userStatus:\n" + " name: Josh\n" + " x-userStatus-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " description: User\n" + " xml:\n" + " name: User\n" + " x-user-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-user:\n" + " name: Josh\n" + " securitySchemes:\n" + " myOauth2Security:\n" + " type: oauth2\n" + " description: myOauthSecurity Description\n" + " in: header\n" + " flows:\n" + " implicit:\n" + " authorizationUrl: http://x.com\n" + " scopes:\n" + " write:pets: modify pets in your account\n" + " x-oauthflow-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-oauthflow:\n" + " name: Josh\n" + " x-oauthflows:\n" + " name: Josh\n" + " x-oauthflows-extensions:\n" + " lastName: Hart\n" + " address: House\n" + " x-security:\n" + " name: Josh\n" + " x-security-extensions:\n" + " lastName: Hart\n" + " address: House\n" + "x-openapi:\n" + " name: Josh\n" + "x-openapi-extensions:\n" + " lastName: Hart\n" + " address: House"; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/extensions/OperationExtensionsResource.java ================================================ package io.swagger.v3.jaxrs2.resources.extensions; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; public class OperationExtensionsResource { @GET @Path("/") @Operation(operationId = "operationId", summary = "Operation Summary", description = "Operation Description", extensions = { @Extension(name = "x-operation", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "x-operation-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) }) public Response getSummaryAndDescription() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/extensions/ParameterExtensionsResource.java ================================================ package io.swagger.v3.jaxrs2.resources.extensions; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class ParameterExtensionsResource { @GET @Path("/") @Operation(operationId = "Id") public void getParameters(@Parameter(extensions = @Extension(name = "x-parameter", properties = { @ExtensionProperty(name = "parameter", value = "value")})) @QueryParam("subscriptionId") String subscriptionId) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/extensions/RequestBodyExtensionsResource.java ================================================ package io.swagger.v3.jaxrs2.resources.extensions; import io.swagger.v3.jaxrs2.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.GET; import javax.ws.rs.Path; public class RequestBodyExtensionsResource { @GET @Path("/user") @Operation(operationId = "Id" ) public void getUser( @Parameter(description = "Parameter with no IN", required = true) @RequestBody(description = "Request Body in Param", extensions = { @Extension(name = "x-extension", properties = { @ExtensionProperty(name = "name", value = "param")}), @Extension(name = "x-extension2", properties = { @ExtensionProperty(name = "another", value = "val")})}) User user) { } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket2144/BaseDTO.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket2144; public class BaseDTO { public String name; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket2144/BaseResource.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket2144; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; public abstract class BaseResource { @GET @Path("/{id}") public T getById(@PathParam("id") String id) { return null; } @GET @Path("/nogeneric/{id}") public BaseDTO getByIdNoGeneric(@PathParam("id") String id) { return null; } @GET @Path("/nogenericsamereturn/{id}") public BaseDTO getByIdNoGenericSameReturn(@PathParam("id") String id) { return null; } @POST @Path("/genericparam") public BaseDTO genericParam(T id) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket2144/Item.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket2144; public class Item extends BaseDTO { public String names; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket2144/ItemResource.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket2144; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @Path("/item") public class ItemResource extends BaseResource { @GET @Path("/{id}") @Override public ItemWithChildren getById(@PathParam("id") String id) { return null; } @GET @Path("/nogeneric/{id}") @Override public ItemWithChildren getByIdNoGeneric(@PathParam("id") String id) { return null; } @GET @Path("/nogenericsamereturn/{id}") @Override public BaseDTO getByIdNoGenericSameReturn(@PathParam("id") String id) { return null; } @POST @Path("/genericparam") public BaseDTO genericParam(ItemWithChildren id) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket2144/ItemWithChildren.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket2144; public class ItemWithChildren extends Item { public String names; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3149/AggregateEndpoint.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3149; public interface AggregateEndpoint extends FirstEndpoint, SecondEndpoint { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3149/FirstEndpoint.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3149; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import javax.ws.rs.POST; import javax.ws.rs.Path; public interface FirstEndpoint { @POST @Path("/") @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Created"), @ApiResponse(responseCode = "400", description = "Bad Request"), @ApiResponse(responseCode = "403", description = "Forbidden"), @ApiResponse(responseCode = "404", description = "Not Found")}) default String firstEndpoint(C param) { return "firstEndpoint-ok"; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3149/MainResource.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3149; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.Path; @Path("/test") @Tag(name = "Test inheritance on default implementation in interfaces") public class MainResource implements AggregateEndpoint { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3149/OriginalEndpoint.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3149; public interface OriginalEndpoint { String originalEndpoint(C c); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3149/SampleDTO.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3149; public class SampleDTO { public String name; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3149/SampleOtherDTO.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3149; public class SampleOtherDTO { public String label; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3149/SecondEndpoint.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3149; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import javax.ws.rs.GET; import javax.ws.rs.Path; public interface SecondEndpoint extends OriginalEndpoint { @GET @Path("/{id}") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Bad Request"), @ApiResponse(responseCode = "403", description = "Forbidden"), @ApiResponse(responseCode = "404", description = "Not Found")}) default String secondEnpoint(C param) { return "secondEnpoint-ok"; } @Override @GET @Path("/original/{id}") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Bad Request"), @ApiResponse(responseCode = "403", description = "Forbidden"), @ApiResponse(responseCode = "404", description = "Not Found")}) default String originalEndpoint(C param) { return "originalEndpoint-ok"; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3426/Parent.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3426; public class Parent { public T get(String input) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3426/Ticket3426Resource.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3426; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @Path("/inheritExample") public class Ticket3426Resource extends Parent { @Override @GET @Path("/{input}") public String get(@PathParam("input") String input) { return super.get(input); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3694/Ticket3694Resource.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3694; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.List; @Path("/") public class Ticket3694Resource implements Ticket3694ResourceInterface { @POST @Path("foo") @Consumes(MediaType.APPLICATION_JSON) @Operation(summary = "Foo List in Interface", tags = "Foo") @Override public Response foo(List foo) { return null; } @POST @Path("bar") @Consumes(MediaType.APPLICATION_JSON) @Operation @Override public String bar(List foo) { return null; } @POST @Path("another") @Consumes(MediaType.APPLICATION_JSON) @Operation @Override public Response another(String foo) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3694/Ticket3694ResourceExtendedType.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3694; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.List; @Path("/") public class Ticket3694ResourceExtendedType implements Ticket3694ResourceInterfaceExtendedType { @POST @Path("foo") @Consumes(MediaType.APPLICATION_JSON) @Operation(summary = "Foo List in Interface", tags = "Foo") @Override public Response foo(List foo) { return null; } @POST @Path("bar") @Consumes(MediaType.APPLICATION_JSON) @Operation @Override public String bar(List foo) { return null; } @POST @Path("another") @Consumes(MediaType.APPLICATION_JSON) @Operation @Override public Response another(String foo) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3694/Ticket3694ResourceInterface.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3694; import javax.ws.rs.core.Response; import java.util.List; public interface Ticket3694ResourceInterface { Response foo(List foo); T bar(List foo); Response another(T foo); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3694/Ticket3694ResourceInterfaceExtendedType.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3694; import javax.ws.rs.core.Response; import java.util.List; public interface Ticket3694ResourceInterfaceExtendedType { Response foo(List foo); T bar(List foo); Response another(T foo); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3694/Ticket3694ResourceInterfaceSimple.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3694; import java.util.List; public interface Ticket3694ResourceInterfaceSimple { T bar(List foo); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3694/Ticket3694ResourceInterfaceSimpleSameReturn.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3694; import javax.ws.rs.core.Response; import java.util.List; public interface Ticket3694ResourceInterfaceSimpleSameReturn { Response bar(List foo); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3694/Ticket3694ResourceSimple.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3694; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import java.util.List; @Path("/") public class Ticket3694ResourceSimple implements Ticket3694ResourceInterfaceSimple { @POST @Path("bar") @Consumes(MediaType.APPLICATION_JSON) @Operation @Override public String bar(List foo) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/generics/ticket3694/Ticket3694ResourceSimpleSameReturn.java ================================================ package io.swagger.v3.jaxrs2.resources.generics.ticket3694; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.List; @Path("/") public class Ticket3694ResourceSimpleSameReturn implements Ticket3694ResourceInterfaceSimpleSameReturn { @POST @Path("bar") @Consumes(MediaType.APPLICATION_JSON) @Operation @Override public Response bar(List foo) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/Category.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Category") public class Category { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } public Category() { } public Category(String name) { this.name = name; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/CustomGenerator.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerators; public class CustomGenerator extends ObjectIdGenerators.PropertyGenerator { private static final long serialVersionUID = 1L; protected CustomGenerator(Class scope) { super(scope); } @Override public ObjectIdGenerator forScope(Class scope) { return null; } @Override public ObjectIdGenerator newForSerialization(Object context) { return null; } @Override public IdKey key(Object key) { return null; } @Override public Object generateId(Object forPojo) { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/ExtensionUser.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "User") @Schema( description = "User", extensions = { @Extension(name = "x-user", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "user-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) public class ExtensionUser { private long id; private String username; private String firstName; private String lastName; private String email; private String password; private String phone; private int userStatus; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "firstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement(name = "lastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone") public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @XmlElement(name = "userStatus") @Schema( description = "User Status", extensions = { @Extension(name = "x-userStatus", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "userStatus-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/FormParamBean.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import javax.ws.rs.BeanParam; import javax.ws.rs.FormParam; public class FormParamBean { @FormParam(value = "param1") private String param1; @FormParam(value = "param2") private String param2; @BeanParam private NestedBeanParam nestedParams; public String getParam1() { return param1; } public void setParam1(String param1) { this.param1 = param1; } public String getParam2() { return param2; } public void setParam2(String param2) { this.param2 = param2; } public NestedBeanParam getNestedParams() { return nestedParams; } public void setNestedParams(final NestedBeanParam nestedParams) { this.nestedParams = nestedParams; } private static class NestedBeanParam { @FormParam(value = "param3") private String param3; public String getParam3() { return param3; } public void setParam3(String param3) { this.param3 = param3; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/Item.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import io.swagger.v3.oas.annotations.media.Schema; public class Item { private String name; private String value; @Schema(example = "Ynl0ZQ==") private byte[] bytes; @Schema(format = "binary", example = "YmluYXJ5") private byte[] binary; private byte[] byteNoAnnotation; public Item() { } public void setBinary(byte[] binary) { this.binary = binary; } public byte[] getBinary() { return binary; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setValue(String value) { this.value = value; } public String getValue() { return value; } public void setBytes(byte[] bytes) { this.bytes = bytes; } public byte[] getBytes() { return bytes; } public void setByteNoAnnotation(byte[] byteNoAnnotation) { this.byteNoAnnotation = byteNoAnnotation; } public byte[] getByteNoAnnotation() { return byteNoAnnotation; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/JacksonBean.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonValue; public class JacksonBean { private String id; private String ignored; private StringValueBean bean; private NotFoundModel model; private NotFoundModel model2; @JsonIgnore public String getIgnored() { return ignored; } public void setIgnored(String ignored) { this.ignored = ignored; } public void setId(String id) { this.id = id; } public void setModel(NotFoundModel model) { this.model = model; } public StringValueBean getBean() { return bean; } public void setBean(StringValueBean bean) { this.bean = bean; } @JsonProperty("identity") public String getId() { return id; } @JsonUnwrapped public NotFoundModel getModel() { return model; } @JsonUnwrapped(prefix = "pre", suffix = "suf") public NotFoundModel getModel2() { return model2; } public void setModel2(NotFoundModel model2) { this.model2 = model2; } public static class StringValueBean { private final String value; @JsonCreator public StringValueBean(String value) { this.value = value; } @JsonValue public String getValue() { return value; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/ListOfStringsBeanParam.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import java.util.List; import javax.ws.rs.QueryParam; public class ListOfStringsBeanParam { @QueryParam(value = "listOfStrings") private List list; public List getList() { return list; } public void setList(List list) { this.list = list; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/ModelWithJsonIdentity.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.ObjectIdGenerators; public class ModelWithJsonIdentity { @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") @JsonProperty("PropertyGeneratorAsId") public SourceDefinition1 testPropertyGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") @JsonProperty("PropertyGeneratorAsProperty") public SourceDefinition1 testPropertyGeneratorAsProperty; public class SourceDefinition1 { public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "driverId") @JsonProperty("ChangedPropertyName") public SourceDefinition2 testChangedPropertyName; @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "driverId") @JsonProperty("ChangedPropertyName2") public SourceDefinition2 testChangedPropertyName2; static public class SourceDefinition2 { @JsonProperty("driverId") public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class) @JsonProperty("SourceWithoutPropertyAsId") public SourceDefinition3 testWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class) @JsonProperty("SourceWithoutPropertyAsProperty") public SourceDefinition3 testWithoutPropertyAsProperty; public class SourceDefinition3 { @JsonProperty("driverId") public String driver; public String name; @JsonProperty("@id") public String id; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "testName1") @JsonProperty("IntSequenceGeneratorAsId") public SourceDefinition4 testIntSequenceGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "testName2") @JsonProperty("IntSequenceGeneratorAsProperty") public SourceDefinition4 testIntSequenceGeneratorAsProperty; public class SourceDefinition4 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) @JsonProperty("IntSequenceWithoutPropertyAsId") public SourceDefinition5 testIntSequenceWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) @JsonProperty("IntSequenceWithoutPropertyAsProperty") public SourceDefinition5 testIntSequenceWithoutPropertyAsProperty; public class SourceDefinition5 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "UUID1") @JsonProperty("UUIDGeneratorAsId") public SourceDefinition6 testUUIDGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "UUID2") @JsonProperty("UUIDGeneratorAsProperty") public SourceDefinition6 testUUIDGeneratorAsProperty; public class SourceDefinition6 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class) @JsonProperty("UUIDGeneratorWithoutPropertyAsId") public SourceDefinition7 testUUIDGeneratorWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class) @JsonProperty("UUIDGeneratorWithoutPropertyAsProperty") public SourceDefinition7 testUUIDGeneratorWithoutPropertyAsProperty; public class SourceDefinition7 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.None.class, property = "testGeneratorsNone") @JsonProperty("GeneratorsNone") public SourceDefinition8 testGeneratorsNone; public class SourceDefinition8 { @JsonProperty("driverId") public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = CustomGenerator.class, property = "name") @JsonProperty("CustomGenerator") public SourceDefinition9 testCustomGenerator; public class SourceDefinition9 { public String driver; public String name; } @JsonIdentityInfo(generator = CustomGenerator.class, property = "name") @JsonProperty("WithoutJsonIdentityReference") public SourceDefinition10 testWithoutJsonIdentityReference; public class SourceDefinition10 { public String driver; public String name; } @JsonProperty("IntSequenceGeneratorAtClassLevel") public SourceDefinition11 testIntSequenceGeneratorAtClassLevel; @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) public class SourceDefinition11 { public String name; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/ModelWithJsonIdentityCyclic.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import java.util.List; public class ModelWithJsonIdentityCyclic { public Long id; public List sourceDefinitions; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") public static class SourceDefinition { public String driver; public String name; @JsonIdentityReference(alwaysAsId=true) @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public ModelWithJsonIdentityCyclic model; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/MultipleBaseBean.java ================================================ package io.swagger.v3.jaxrs2.resources.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleBaseBean", subTypes = { MultipleSub1Bean.class, MultipleSub2Bean.class } ) public class MultipleBaseBean { public String beanType; public int a; public String b; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/MultipleSub1Bean.java ================================================ package io.swagger.v3.jaxrs2.resources.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleSub1Bean" ) public class MultipleSub1Bean extends MultipleBaseBean { public int c; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/MultipleSub2Bean.java ================================================ package io.swagger.v3.jaxrs2.resources.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleSub2Bean" ) public class MultipleSub2Bean extends MultipleBaseBean { public int d; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/NestedBeanParam.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import javax.ws.rs.BeanParam; import javax.ws.rs.DefaultValue; import javax.ws.rs.QueryParam; public class NestedBeanParam { @BeanParam private NestedClass nestedParams; public NestedClass getNestedParams() { return nestedParams; } public void setNestedParams(final NestedClass nestedParams) { this.nestedParams = nestedParams; } public class NestedClass { @QueryParam(value = "queryParam") @DefaultValue("10") private Integer queryParam = 10; public Integer getQueryParam() { return queryParam; } public void setQueryParam(final Integer queryParam) { this.queryParam = queryParam; } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/NotFoundModel.java ================================================ package io.swagger.v3.jaxrs2.resources.model; public class NotFoundModel { int code; String message; public NotFoundModel() { } public NotFoundModel(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/Pet.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.util.ArrayList; import java.util.List; @XmlRootElement(name = "Pet") public class Pet { private long id; private Category category; private String name; private List photoUrls = new ArrayList(); private List tags = new ArrayList(); private String status; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "category") public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElementWrapper(name = "photoUrls") @XmlElement(name = "photoUrl") public List getPhotoUrls() { return photoUrls; } public void setPhotoUrls(List photoUrls) { this.photoUrls = photoUrls; } @XmlElementWrapper(name = "tags") @XmlElement(name = "tag") public List getTags() { return tags; } public void setTags(List tags) { this.tags = tags; } @XmlElement(name = "status") @Schema(description = "pet status in the store", allowableValues = "available,pending,sold") public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/Tag.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Tag") public class Tag { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/model/User.java ================================================ package io.swagger.v3.jaxrs2.resources.model; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "User") public class User { private long id; private String username; private String firstName; private String lastName; private String email; private String password; private String phone; private int userStatus; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "firstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement(name = "lastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone") public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @XmlElement(name = "userStatus") @Schema(description = "User Status") //, allowableValues = {"1","2","3"}) public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/rs/AbstractEntityRestService.java ================================================ package io.swagger.v3.jaxrs2.resources.rs; public abstract class AbstractEntityRestService implements EntityRestService { public DTO create(DTO object) throws Exception { return null; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/rs/EntityRestService.java ================================================ package io.swagger.v3.jaxrs2.resources.rs; import javax.ws.rs.POST; import javax.ws.rs.Path; public interface EntityRestService { @POST @Path("/") public DTO create(DTO object) throws Exception; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/rs/PersistentDTO.java ================================================ package io.swagger.v3.jaxrs2.resources.rs; public class PersistentDTO { private String guid; public void setGuid(String guid) { this.guid = guid; } public String getGuid() { return guid; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/rs/ProcessTokenDTO.java ================================================ package io.swagger.v3.jaxrs2.resources.rs; public class ProcessTokenDTO extends PersistentDTO { private String name; } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/rs/ProcessTokenRestService.java ================================================ package io.swagger.v3.jaxrs2.resources.rs; import javax.ws.rs.Consumes; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("token") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public class ProcessTokenRestService extends AbstractEntityRestService { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/siblings/Category.java ================================================ package io.swagger.v3.jaxrs2.resources.siblings; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "parent") public class Category { private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/siblings/Pet.java ================================================ package io.swagger.v3.jaxrs2.resources.siblings; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "Pet") public class Pet { private Category category; @Schema(description = "child") public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/siblings/PetSimple.java ================================================ package io.swagger.v3.jaxrs2.resources.siblings; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "Pet") public class PetSimple { } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ticket3624/Service.java ================================================ package io.swagger.v3.jaxrs2.resources.ticket3624; import io.swagger.v3.jaxrs2.resources.ticket3624.model.ByIdResponse; import io.swagger.v3.jaxrs2.resources.ticket3624.model.ContainerizedResponse; import io.swagger.v3.jaxrs2.resources.ticket3624.model.Response; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Tag(name = "ExampleService") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @Path(Service.ROOT_PATH) public interface Service { String ROOT_PATH = "/example"; @GET @Path("/model") @Operation(summary = " Retrieve models for display to the user") Response getModels(); @GET @Path("/model/by/ids") @Operation(summary = " Retrieve models by their ids") ByIdResponse getModelsById(); @GET @Path("/containerized/model") @Operation(summary = " Retrieve review insights for a specific product") ContainerizedResponse getContainerizedModels(); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ticket3624/model/ByIdResponse.java ================================================ package io.swagger.v3.jaxrs2.resources.ticket3624.model; import java.util.Map; public abstract class ByIdResponse { public abstract Map getModelsById(); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ticket3624/model/ContainerizedResponse.java ================================================ package io.swagger.v3.jaxrs2.resources.ticket3624.model; import java.util.List; public abstract class ContainerizedResponse { public abstract List getContainerizedModels(); public abstract int getTotalCount(); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ticket3624/model/Model.java ================================================ package io.swagger.v3.jaxrs2.resources.ticket3624.model; import io.swagger.v3.oas.annotations.media.Schema; import java.util.Optional; public abstract class Model { // this is the ID of the review public abstract int getId(); public abstract String getText(); public abstract String getTitle(); public abstract boolean isActive(); public abstract Optional getOptionalString(); public abstract Optional getParent(); @Schema public abstract Optional getSchemaParent(); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ticket3624/model/ModelContainer.java ================================================ package io.swagger.v3.jaxrs2.resources.ticket3624.model; import java.util.Optional; public abstract class ModelContainer { public abstract Optional getModel(); public abstract int getId(); public abstract String getText(); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/resources/ticket3624/model/Response.java ================================================ package io.swagger.v3.jaxrs2.resources.ticket3624.model; import java.util.List; public abstract class Response { public abstract List getModels(); public abstract int getCount(); } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedResource.java ================================================ package io.swagger.v3.jaxrs2.schemaResolution; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("test") public class SchemaResolutionAnnotatedResource { @GET @Path("/inlineSchemaSecond") public InlineSchemaSecond inlineSchemaSecond(@Schema(description = "InlineSchemaSecond API", schemaResolution = Schema.SchemaResolution.INLINE) InlineSchemaSecond inlineSchemaSecond) { return null; } @GET @Path("/inlineSchemaFirst") public InlineSchemaFirst inlineSchemaFirst() { return null; } static class InlineSchemaFirst { // public String foo; @Schema(description = "InlineSchemaFirst property 1", nullable = true, schemaResolution = Schema.SchemaResolution.ALL_OF_REF) public InlineSchemaPropertyFirst property1; private InlineSchemaPropertyFirst property2; @Schema(description = " InlineSchemaFirst property 2", example = "example 2", schemaResolution = Schema.SchemaResolution.INLINE) public InlineSchemaPropertyFirst getProperty2() { return null; } } static class InlineSchemaSecond { public String foo; @Schema(description = "InlineSchemaSecond property 1", nullable = true) public InlineSchemaPropertySecond propertySecond1; private InlineSchemaPropertyFirst property2; @Schema(description = "InlineSchemaSecond property 2", example = "InlineSchemaSecond example 2") public InlineSchemaPropertyFirst getProperty2() { return null; } } @Schema(description = "property", example = "example") static class InlineSchemaPropertyFirst { public String bar; } @Schema(description = "propertysecond", example = "examplesecond") static class InlineSchemaPropertySecond { public InlineSchemaSimple bar; } static class InlineSchemaSimple { @Schema(description = "property 1", schemaResolution = Schema.SchemaResolution.INLINE) public InlineSchemaPropertySimple property1; private InlineSchemaPropertySimple property2; @Schema(description = "property 2", example = "example", schemaResolution = Schema.SchemaResolution.ALL_OF_REF) public InlineSchemaPropertySimple getProperty2() { return null; } } @Schema(description = "property") static class InlineSchemaPropertySimple { public String bar; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionAnnotatedSimpleResource.java ================================================ package io.swagger.v3.jaxrs2.schemaResolution; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("test") public class SchemaResolutionAnnotatedSimpleResource { @GET @Path("/inlineSchemaFirst") public InlineSchemaFirst inlineSchemaFirst() { return null; } static class InlineSchemaFirst { private InlineSchemaPropertyFirst property2; @Schema(description = " InlineSchemaFirst property 2", example = "example 2", schemaResolution = Schema.SchemaResolution.INLINE) public InlineSchemaPropertyFirst getProperty2() { return null; } } @Schema(description = "property", example = "example") static class InlineSchemaPropertyFirst { // public String bar; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResource.java ================================================ package io.swagger.v3.jaxrs2.schemaResolution; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("test") public class SchemaResolutionResource { @GET @Path("/inlineSchemaSecond") public InlineSchemaSecond inlineSchemaSecond(@Schema(description = "InlineSchemaSecond API") InlineSchemaSecond inlineSchemaSecond) { return null; } @GET @Path("/inlineSchemaFirst") public InlineSchemaFirst inlineSchemaFirst() { return null; } static class InlineSchemaFirst { // public String foo; @Schema(description = "InlineSchemaFirst property 1", nullable = true) public InlineSchemaPropertyFirst property1; private InlineSchemaPropertyFirst property2; @Schema(description = " InlineSchemaFirst property 2", example = "example 2") public InlineSchemaPropertyFirst getProperty2() { return null; } } static class InlineSchemaSecond { public String foo; @Schema(description = "InlineSchemaSecond property 1", nullable = true) public InlineSchemaPropertySecond propertySecond1; private InlineSchemaPropertyFirst property2; @Schema(description = "InlineSchemaSecond property 2", example = "InlineSchemaSecond example 2") public InlineSchemaPropertyFirst getProperty2() { return null; } } @Schema(description = "property", example = "example") static class InlineSchemaPropertyFirst { public String bar; } @Schema(description = "propertysecond", example = "examplesecond") static class InlineSchemaPropertySecond { public InlineSchemaSimple bar; } static class InlineSchemaSimple { @Schema(description = "property 1") public InlineSchemaPropertySimple property1; private InlineSchemaPropertySimple property2; @Schema(description = "property 2", example = "example") public InlineSchemaPropertySimple getProperty2() { return null; } } @Schema(description = "property") static class InlineSchemaPropertySimple { public String bar; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/schemaResolution/SchemaResolutionResourceSimple.java ================================================ package io.swagger.v3.jaxrs2.schemaResolution; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @Path("test") public class SchemaResolutionResourceSimple { @GET @Path("/inlineSchemaFirst") @ApiResponse(description = "InlineSchemaFirst Response API", content = @Content(schema = @Schema(implementation = InlineSchemaFirst.class))) public Response inlineSchemaFirst() { return null; } @GET @Path("/inlineSchemaSecond") public void inlineSchemaFirst(@Schema(description = "InlineSchemaSecond API") InlineSchemaFirst inlineSchemaFirst) { } static class InlineSchemaFirst { // public String foo; @Schema(description = "InlineSchemaFirst property 1", nullable = true) public InlineSchemaPropertyFirst property1; } @Schema(description = "property", example = "example") static class InlineSchemaPropertyFirst { public String bar; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/util/ServletUtilsTest.java ================================================ package io.swagger.v3.jaxrs2.util; import org.testng.annotations.Test; import javax.ws.rs.core.MultivaluedHashMap; import java.net.URLEncoder; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import static java.nio.charset.StandardCharsets.UTF_8; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertNotNull; public class ServletUtilsTest { @Test(description = "convert query parameters to multivaluedmap") public void convertWithRightOutputSize() throws Exception { Map params = new HashMap<>(); params.put("key1", new String[]{"value1", "value2"}); params.put("key2", new String[]{"value2", "value3", "value4", "value4"}); MultivaluedHashMap multivaluedMap = ServletUtils.getQueryParams(params); assertEquals(multivaluedMap.size(), 2); assertEquals(multivaluedMap.get("key1").size(), 2); assertEquals(multivaluedMap.get("key2").size(), 4); assertTrue(multivaluedMap.containsKey("key1")); assertTrue(multivaluedMap.containsKey("key2")); } @Test(description = "convert query parameters to multivaluedmap with decoded values") public void convertWithDecodedValues() throws Exception { Map params = new HashMap<>(); params.put(URLEncoder.encode("key1&", UTF_8.name()), new String[]{"value1", URLEncoder.encode("value2?", UTF_8.name())}); params.put("key2", new String[]{URLEncoder.encode("value2", UTF_8.name()), "value3", "value4", "value4"}); assertEquals(params.get("key1%26"), new String[]{"value1", "value2%3F"}); MultivaluedHashMap multivaluedHashMap = ServletUtils.getQueryParams(params); assertEquals(multivaluedHashMap.size(), 2); assertNotNull(multivaluedHashMap.get("key1&")); assertEquals(multivaluedHashMap.get("key1&").size(), 2); assertEquals(multivaluedHashMap.get("key1&"), Arrays.asList("value1", "value2?")); assertEquals(multivaluedHashMap.get("key2"), Arrays.asList("value2", "value3", "value4", "value4")); } } ================================================ FILE: modules/swagger-jaxrs2/src/test/java/org/my/project/resources/ResourceInPackageB.java ================================================ package org.my.project.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import java.util.ArrayList; @Path("/packageB") public class ResourceInPackageB { @Operation(operationId = "test.") @GET public void getTest(@Parameter(name = "test") ArrayList tenantId) { return; } } ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/BinaryParameterResource.yaml ================================================ openapi: 3.0.1 paths: /binary: post: summary: Create new item description: Post operation with entity in a body operationId: createItem requestBody: content: application/json: schema: $ref: "#/components/schemas/Item" required: true responses: "201": headers: Location: style: simple content: application/json: schema: $ref: "#/components/schemas/Item" components: schemas: Item: type: object properties: name: type: string value: type: string bytes: type: string format: byte example: Ynl0ZQ== binary: type: string format: binary example: YmluYXJ5 byteNoAnnotation: type: string format: byte ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/AnnotatedModelAndContentExample.yaml ================================================ openapi: 3.0.1 paths: /test: post: operationId: testAnnotatedModel requestBody: description: Created user object content: application/json: schema: $ref: "#/components/schemas/AnnotatedSubscription" examples: Default Request 2: summary: Subscription Example 2 description: Default Request 2 value: subscriptionId: "12" subscriptionItem: subscriptionItemId: "22" Default Request: summary: Subscription Example description: Default Request value: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" required: true responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/AnnotatedSubscription" components: schemas: AnnotatedSubscriptionItem: type: object properties: subscriptionItemId: type: string example: subscriptionItemId: "1" AnnotatedSubscription: type: object properties: subscriptionId: type: string subscriptionItem: $ref: "#/components/schemas/AnnotatedSubscriptionItem" example: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/AnnotatedModelExample.yaml ================================================ openapi: 3.0.1 paths: /test: post: operationId: testAnnotatedModel requestBody: description: Created user object content: '*/*': schema: $ref: "#/components/schemas/AnnotatedSubscription" required: true responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/AnnotatedSubscription" components: schemas: AnnotatedSubscriptionItem: type: object properties: subscriptionItemId: type: string example: subscriptionItemId: "1" AnnotatedSubscription: type: object properties: subscriptionId: type: string subscriptionItem: $ref: "#/components/schemas/AnnotatedSubscriptionItem" example: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/ParameterExample.yaml ================================================ openapi: 3.0.1 paths: /test: post: operationId: testRequestBody parameters: - in: query description: subscription param required: true examples: ex 2: description: ex 2 value: subscriptionId: "12" subscriptionItem: subscriptionItemId: "22" ex 1: description: ex 1 value: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" example: 1 content: application/json: schema: type: string description: the Sub readOnly: true example: Schema example examples: Default Request: summary: Subscription Example description: Subscription Example Description value: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/Subscription" components: schemas: SubscriptionItem: type: object properties: subscriptionItemId: type: string Subscription: type: object properties: subscriptionId: type: string subscriptionItem: $ref: "#/components/schemas/SubscriptionItem" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/RequestBodyContentExample.yaml ================================================ openapi: 3.0.1 paths: /test: post: operationId: testRequestBody requestBody: description: Created user object content: '*/*': schema: $ref: "#/components/schemas/Subscription" examples: Default Request: summary: Subscription Example description: Default Request value: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" required: true responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/Subscription" components: schemas: SubscriptionItem: type: object properties: subscriptionItemId: type: string Subscription: type: object properties: subscriptionId: type: string subscriptionItem: $ref: "#/components/schemas/SubscriptionItem" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/RequestBodyContentExampleWithConsumes.yaml ================================================ openapi: 3.0.1 paths: /test: post: operationId: testRequestBody requestBody: description: Created user object content: 'application/json': schema: $ref: "#/components/schemas/Subscription" examples: Default Request: summary: Subscription Example description: Default Request value: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" required: true responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/Subscription" components: schemas: SubscriptionItem: type: object properties: subscriptionItemId: type: string Subscription: type: object properties: subscriptionId: type: string subscriptionItem: $ref: "#/components/schemas/SubscriptionItem" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/RequestBodyContentExampleWithMediatype.yaml ================================================ openapi: 3.0.1 paths: /test: post: operationId: testRequestBody requestBody: description: Created user object content: 'application/json': schema: $ref: "#/components/schemas/Subscription" examples: Default Request: summary: Subscription Example description: Default Request value: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" required: true responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/Subscription" components: schemas: SubscriptionItem: type: object properties: subscriptionItemId: type: string Subscription: type: object properties: subscriptionId: type: string subscriptionItem: $ref: "#/components/schemas/SubscriptionItem" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/RequestBodyContentExampleWithSchema.yaml ================================================ openapi: 3.0.1 paths: /test: post: operationId: testRequestBody requestBody: description: Created user object content: '*/*': schema: type: string description: the Sub readOnly: true example: Schema example examples: Default Request: summary: Subscription Example description: Default Request value: 3 required: true responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/Subscription" components: schemas: SubscriptionItem: type: object properties: subscriptionItemId: type: string Subscription: type: object properties: subscriptionId: type: string subscriptionItem: $ref: "#/components/schemas/SubscriptionItem" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/RequestBodyContentExampleWithSchemaImplementation.yaml ================================================ openapi: 3.0.1 paths: /test: post: operationId: testRequestBody requestBody: description: Created user object content: '*/*': schema: $ref: "#/components/schemas/Subscription" examples: Default Request: summary: Subscription Example description: Default Request value: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" required: true responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/Subscription" components: schemas: SubscriptionItem: type: object properties: subscriptionItemId: type: string Subscription: type: object properties: subscriptionId: type: string subscriptionItem: $ref: "#/components/schemas/SubscriptionItem" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/ResponseExample.yaml ================================================ openapi: 3.0.1 paths: /test: post: description: subscribes a client to updates relevant to the requestor's account, as identified by the input token. The supplied url will be used as the delivery address for response payloads operationId: subscribe responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/SubscriptionResponse" examples: Default Response: summary: Subscription Response Example description: Default Response value: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" components: schemas: SubscriptionResponse: type: object properties: subscriptionId: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/ResponseExampleSchema.yaml ================================================ openapi: 3.0.1 paths: /test: post: description: subscribes a client to updates relevant to the requestor's account, as identified by the input token. The supplied url will be used as the delivery address for response payloads operationId: subscribe responses: default: description: test description content: '*/*': schema: type: string description: the generated UUID format: uuid readOnly: true example: Schema example examples: Default Response: summary: Subscription Response Example description: Default Response value: SubscriptionResponse components: schemas: SubscriptionResponse: type: object properties: subscriptionId: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/examples/ResponseExampleSchemaImplementation.yaml ================================================ openapi: 3.0.1 paths: /test: post: description: subscribes a client to updates relevant to the requestor's account, as identified by the input token. The supplied url will be used as the delivery address for response payloads operationId: subscribe responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/Subscription" examples: Default Response: summary: Subscription Response Example description: Default Response value: subscriptionId: "1" subscriptionItem: subscriptionItemId: "2" components: schemas: SubscriptionItem: type: object properties: subscriptionItemId: type: string SubscriptionResponse: type: object properties: subscriptionId: type: string Subscription: type: object properties: subscriptionId: type: string subscriptionItem: $ref: "#/components/schemas/SubscriptionItem" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/integration/openapi-configuration.json ================================================ { "resourcePackages": [ "com.my.project.resources", "org.my.project.resources" ], "openAPI": { "info": { "version": "1.0", "title": "Swagger Pet Sample App", "description": "This is a TEST AAsample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", "termsOfService": "http://swagger.io/terms/", "contact": { "email": "apiteam@swagger.io" }, "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.html" } } } } ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/logback-test.xml ================================================ ERROR %d [%thread]%level %logger - %msg%n ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/EmptyPetResource.yaml ================================================ openapi: 3.0.1 ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/FullPetResource.yaml ================================================ openapi: 3.0.1 info: title: Pet Resource Example description: API Definition termsOfService: Terms of service contact: name: Fred url: http://gigantic-server.com email: Fred@gigagantic-server.com license: name: Apache 2.0 url: http://foo.bar version: "2.0" externalDocs: description: definition docs desc servers: - url: http://foo description: server 1 security: - req 1: - a - b - req 2: - b - c tags: - name: Tag 1 description: desc 1 externalDocs: description: docs desc - name: Tag 2 description: desc 2 externalDocs: description: docs desc 2 - name: Tag 3 - name: Definition First Tag - name: Definition Second Tag full description: desc definition - name: Fourth Tag Full description: desc externalDocs: description: docs desc - name: Fifth Tag Full description: desc class externalDocs: description: docs desc class paths: /pet: put: summary: Update an existing pet operationId: updatePet requestBody: description: Pet object that needs to be added to the store content: application/json: schema: $ref: "#/components/schemas/Pet" required: true responses: "400": description: Invalid ID supplied "404": description: Pet not found "405": description: Validation exception post: summary: Add a new pet to the store operationId: addPet requestBody: description: Pet object that needs to be added to the store content: application/json: schema: $ref: "#/components/schemas/Pet" application/xml: schema: $ref: "#/components/schemas/Pet" required: true responses: "405": description: Invalid input /pet/bodyid: post: summary: Add a new pet to the store passing an integer with generic parameter annotation operationId: addPetByInteger requestBody: description: Pet object that needs to be added to the store content: application/json: schema: type: integer format: int32 application/xml: schema: type: integer format: int32 required: true responses: "405": description: Invalid input /pet/bodyidnoannotation: post: summary: Add a new pet to the store passing an integer without parameter annotation operationId: addPetByIntegerNoAnnotation requestBody: content: application/json: schema: type: integer format: int32 application/xml: schema: type: integer format: int32 responses: "405": description: Invalid input /pet/bodynoannotation: post: summary: Add a new pet to the store no annotation operationId: addPetNoAnnotation requestBody: content: application/json: schema: $ref: "#/components/schemas/Pet" application/xml: schema: $ref: "#/components/schemas/Pet" responses: "405": description: Invalid input /pet/findByStatus: get: summary: Finds Pets by status description: Multiple status values can be provided with comma separated strings operationId: findPetsByStatus parameters: - name: status in: query description: Status values that need to be considered for filter required: true schema: type: string - name: skip in: query schema: type: integer format: int32 - name: limit in: query schema: type: integer format: int32 responses: default: content: application/json: schema: $ref: "#/components/schemas/Pet" "400": description: Invalid status value /pet/findByTags: get: summary: Finds Pets by tags description: "Multiple tags can be provided with comma separated strings. Use\ \ tag1, tag2, tag3 for testing." operationId: findPetsByTags parameters: - name: tags in: query description: Tags to filter by required: true schema: type: string responses: default: description: Pets matching criteria content: application/json: schema: $ref: "#/components/schemas/Pet" "400": description: Invalid tag value deprecated: true /pet/{petId}: get: summary: Find pet by ID description: Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions operationId: getPetById parameters: - name: petId in: path description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 responses: default: description: The pet content: application/json: schema: $ref: "#/components/schemas/Pet" application/xml: schema: $ref: "#/components/schemas/Pet" "400": description: Invalid ID supplied "404": description: Pet not found /complexcallback: get: summary: Simple get operation operationId: getWithNoParameters_1 parameters: - name: id in: query description: idParam schema: $ref: "#/components/schemas/User" responses: "200": description: voila! callbacks: testCallback1: http://www.url.com: get: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: integer format: int32 testCallback2: http://www.url2.com: get: summary: get a review operationId: getAnSpecificReviews responses: "200": description: successful operation content: application/json: schema: $ref: "#/components/schemas/User" /multiplecallback: get: summary: Simple get operation operationId: getWithNoParameters responses: "200": description: voila! callbacks: testCallback1: http://www.url.com: get: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: integer format: int32 testCallback2: http://$request.query.url: {} /repeatablecallback: get: summary: Simple get operation operationId: getWithNoParameters_2 responses: "200": description: voila! callbacks: testCallback: http://$requests.query.url: {} testCallback1: http://www.url.com: get: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: integer format: int32 testCallback2: http://$request.query.url: {} /simplecallback: get: summary: Simple get operation operationId: getWithNoParameters_3 responses: "200": description: voila! callbacks: testCallback1: http://www.url.com: get: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: integer format: int32 /example: post: description: subscribes a client to updates relevant to the requestor's account operationId: subscribe parameters: - name: subscriptionId in: path required: true style: simple schema: type: string description: Schema example: Subscription example examples: subscriptionId_1: summary: Subscription number 12345 description: subscriptionId_1 value: 12345 externalValue: Subscription external value 1 subscriptionId_2: summary: Subscription number 54321 description: subscriptionId_2 value: 54321 externalValue: Subscription external value 2 example: example requestBody: description: Created user object content: '*/*': schema: type: string description: the generated UUID format: uuid readOnly: true example: Schema example examples: Default Request: summary: Subscription Request Example description: Default Request value: SubscriptionRequest externalValue: Subscription Request Value required: true responses: default: description: test description content: '*/*': schema: type: string description: the generated UUID format: uuid readOnly: true example: Schema example examples: Default Response: summary: Subscription Response Example description: Default Response value: SubscriptionResponse externalValue: Subscription Response value 1 /links: get: operationId: getUserWithAddress_1 parameters: - name: userId in: query schema: type: string responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/User" links: address: operationId: getAddress parameters: userId: $request.query.userId user: operationId: getUser parameters: userId: $request.query.userId /sameOperationName: get: description: Same Operation Name operationId: getUser responses: default: description: default response content: '*/*': schema: type: string delete: description: Same Operation Name Duplicated operationId: getUser_1 requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: type: string /{petId}: get: summary: Find pet by ID description: Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions externalDocs: description: External Annotation Documentation url: http://url.me operationId: petId parameters: - name: petId in: path description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 responses: default: description: default response content: '*/*': {} /fullyannotatedoperation/{petId}: get: summary: Find pet by ID description: Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions operationId: petId_1 parameters: - name: petId in: path description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 responses: default: description: The pet content: '*/*': schema: $ref: "#/components/schemas/Pet" "400": description: Invalid ID supplied "404": description: Pet not found /interfaceoperation/{petId}: get: summary: Find pet by ID Operation in SubResource description: Returns a pet in SubResource operationId: getPetById_1 parameters: - name: petId in: path description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 responses: default: description: default response content: '*/*': {} /notannotatedoperation: get: operationId: getUser_2 responses: default: description: default response content: '*/*': schema: type: string /notannotatedoperationduplicated: get: operationId: getUser_3 requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: type: string /operationsresource: get: summary: Find pet by ID description: "combinatedfullyannotatedoperation/{petId}" operationId: petId_2 parameters: - name: petId in: query description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 requestBody: content: '*/*': schema: type: string responses: default: description: The pet content: '*/*': schema: $ref: "#/components/schemas/Pet" "400": description: Invalid ID supplied "404": description: Pet not found put: description: combinatedsameOperationName operationId: combinated sameOperationName responses: default: description: default response content: '*/*': schema: type: string post: operationId: getUser_5 requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: type: string head: description: combinatedsameOperationNameDuplicated operationId: combinatedsameOperationNameDuplicated requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: type: string /operationsresource2: get: operationId: getUser_4 responses: default: description: default response content: '*/*': schema: type: string /operationwithouannotation: get: operationId: getUser_6 responses: default: description: default response content: '*/*': schema: type: string /serversoperation: get: description: Pets Example operationId: Pets responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/Pet" servers: - url: http://foo2 description: server 2 /arrayschema: post: description: "subscribes a client to updates relevant to the requestor's account,\ \ as identified by the input token. The supplied url will be used as the\ \ delivery address for response payloads" operationId: subscribe_1 parameters: - name: arrayParameter in: query required: true explode: true schema: maxItems: 10 minItems: 1 uniqueItems: true type: array items: $ref: "#/components/schemas/SubscriptionResponse" responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/SubscriptionResponse" /complexparameter: get: operationId: create User_1 parameters: - name: phone in: path description: Phone required: true schema: type: string - name: id in: query description: idParam schema: type: string - name: lastName in: query schema: type: string - name: address in: query description: address schema: $ref: "#/components/schemas/User" requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" /multiplenoannotatedparameter: post: operationId: create User requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': {} /openapijaxrsannotatedparameter: get: operationId: create User_2 parameters: - name: id in: query description: idParam schema: type: string responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" /openapiwithcontentjaxrsannotatedparameter: get: operationId: create User_3 parameters: - name: id in: query description: idParam content: '*/*': schema: type: string description: Id Schema Definition responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" /openapiwithimplementationjaxrsannotatedparameter: get: operationId: create User_4 parameters: - name: id in: query description: idParam schema: $ref: "#/components/schemas/User" responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" /parameters: post: description: "subscribes a client to updates relevant to the requestor's account,\ \ as identified by the input token. The supplied url will be used as the\ \ delivery address for response payloads" operationId: subscribe_3 parameters: - name: subscriptionId in: path required: true style: simple schema: $ref: "#/components/schemas/SubscriptionResponse" - name: formId in: query required: true schema: type: string example: Example - name: explodeFalse in: query required: true explode: false schema: $ref: "#/components/schemas/SubscriptionResponse" - name: explodeTrue in: query required: true explode: true schema: $ref: "#/components/schemas/SubscriptionResponse" - name: explodeAvoiding in: query required: true schema: type: string description: the generated id format: id readOnly: true - name: arrayParameter in: query required: true explode: true content: application/json: schema: type: number description: the generated id readOnly: true application/xml: schema: type: number description: the generated id readOnly: true - name: arrayParameterImplementation in: query required: true explode: true schema: maxItems: 10 minItems: 1 uniqueItems: true type: array items: $ref: "#/components/schemas/SubscriptionResponse" - name: arrayParameterImplementation2 in: query required: true explode: true schema: $ref: "#/components/schemas/SubscriptionResponse" - name: id in: query description: idParam schema: type: string responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/SubscriptionResponse" /repeatableparameter: post: description: "subscribes a client to updates relevant to the requestor's account,\ \ as identified by the input token. The supplied url will be used as the\ \ delivery address for response payloads" operationId: subscribe_2 parameters: - name: subscriptionId in: path required: true style: simple schema: $ref: "#/components/schemas/SubscriptionResponse" - name: formId in: query required: true schema: type: string example: Example - name: explodeFalse in: query required: true explode: false schema: $ref: "#/components/schemas/SubscriptionResponse" - name: explodeTrue in: query required: true explode: true schema: $ref: "#/components/schemas/SubscriptionResponse" - name: explodeAvoiding in: query required: true schema: type: string description: the generated id format: id readOnly: true - name: arrayParameter in: query required: true explode: true content: application/json: schema: type: number description: the generated id readOnly: true application/xml: schema: type: number description: the generated id readOnly: true - name: arrayParameterImplementation in: query required: true explode: true schema: maxItems: 10 minItems: 1 uniqueItems: true type: array items: $ref: "#/components/schemas/SubscriptionResponse" - name: arrayParameterImplementation2 in: query required: true explode: true schema: $ref: "#/components/schemas/SubscriptionResponse" responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/SubscriptionResponse" /singlejaxrsannotatedparameter: get: operationId: create User_5 parameters: - name: id in: query schema: type: string responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" /singlenoannotatedparameter: get: operationId: create User_6 requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" /methodWithRequestBodyAndTwoParameters: post: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyAndTwoParameters_3 parameters: - name: name in: query schema: type: string - name: code in: query schema: type: string requestBody: description: Created user object content: '*/*': schema: $ref: "#/components/schemas/User" required: true responses: default: description: default response content: '*/*': {} /methodWithRequestBodyWithoutContentWithoutImplementation: get: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyWithoutContentWithoutImplementation_1 requestBody: description: Created user object content: '*/*': schema: type: string description: User description example: User Description required: true responses: default: description: default response content: '*/*': {} /requestbodymethodpriority: post: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyAndTwoParameters_1 requestBody: description: Created user object on Method content: '*/*': schema: $ref: "#/components/schemas/User" required: true responses: default: description: default response content: '*/*': {} /requestbodyparameterpriority: post: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyAndTwoParameters_2 requestBody: description: Created user object inside Parameter content: '*/*': schema: $ref: "#/components/schemas/User" required: true responses: default: description: default response content: '*/*': {} /methodWithOneSimpleRequestBody: delete: summary: Delete pet description: Deleting pet. operationId: methodWithOneSimpleRequestBody requestBody: content: application/json: schema: type: integer format: int32 application/xml: schema: type: integer format: int32 responses: default: description: default response content: '*/*': {} /methodWithRequestBodyWithoutAnnotation: put: summary: Modify user description: Modifying user. operationId: methodWithRequestBodyWithoutAnnotation requestBody: content: '*/*': schema: $ref: "#/components/schemas/User" responses: default: description: default response content: '*/*': {} /methodWithRequestBodyWithoutAnnotationAndTwoConsumes: put: summary: Modify pet description: Modifying pet. operationId: methodWithRequestBodyWithoutAnnotationAndTwoConsumes requestBody: content: application/json: schema: $ref: "#/components/schemas/User" application/xml: schema: $ref: "#/components/schemas/User" responses: default: description: default response content: '*/*': {} /methodWithRequestBodyWithoutContent: get: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyWithoutContent requestBody: description: Created user object content: '*/*': schema: $ref: "#/components/schemas/User" required: true responses: default: description: default response content: '*/*': {} /methodWithTwoRequestBodyWithAnnotationAndTwoConsumes: post: summary: Create pet description: Creating pet. operationId: methodWithTwoRequestBodyWithAnnotationAndTwoConsumes requestBody: description: Request Body User content: application/json: schema: $ref: "#/components/schemas/User" application/xml: schema: $ref: "#/components/schemas/User" responses: default: description: default response content: '*/*': {} /methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes: post: summary: Create pet description: Creating pet. operationId: methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes requestBody: content: application/json: schema: $ref: "#/components/schemas/Pet" application/xml: schema: $ref: "#/components/schemas/Pet" responses: default: description: default response content: '*/*': {} /methodWithoutRequestBodyAndTwoParameters: delete: summary: Delete user description: This can only be done by the logged in user. operationId: methodWithoutRequestBodyAndTwoParameters parameters: - name: name in: query schema: type: string - name: code in: query schema: type: string responses: default: description: default response content: '*/*': {} /complexresponse: get: summary: Find pets description: Returns the Pets operationId: getPets responses: "200": description: Response inside Operation content: '*/*': schema: $ref: "#/components/schemas/Pet" default: description: Default Pet content: '*/*': schema: type: string description: Default Pet example: New Pet "404": description: Couldn't find pet /implementationresponse: get: summary: Simple get operation description: Defines a simple get operation with no inputs and a complex output object operationId: getWithPayloadResponse responses: "200": description: voila! content: application/json: schema: $ref: "#/components/schemas/SecondSampleResponseSchema" "400": description: boo content: '*/*': schema: $ref: "#/components/schemas/GenericError" deprecated: true "/arrayresponseinmethod": get: operationId: arrayResponseWithTypeImplementation responses: default: content: "*/*": schema: type: array description: Array description items: "$ref": "#/components/schemas/PetInfo" "/responseinmethod": get: summary: Find pets description: Returns the Pets operationId: getPets_1 responses: "200": description: Status OK /noimplementationresponseresource: get: operationId: getUser_7 parameters: - name: userId in: query schema: type: string responses: "400": description: test description links: user: operationId: getUser parameters: userId: $request.query.userId "200": description: 200 description links: pet: operationId: getUser parameters: userId: $request.query.userId /noresponse: get: summary: Find pets description: Returns the Pets operationId: getPets_2 responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" /responseinoperation: get: summary: Find Users description: Returns the Users operationId: getUsers responses: "200": description: Status OK /priorityresponses: get: summary: Find pets description: Returns the Pets operationId: getPets_3 responses: "200": description: Inside Method Operation /security: get: description: description operationId: Operation Id responses: default: description: default response content: '*/*': {} security: - security_key: - write:pets - read:pets - myOauth2Security: - write:pets put: description: description 3 operationId: Operation Id 3 requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': {} security: - security_key: - write:pets - read:pets - myOauth2Security: - write:pets - security_key3: - write:pets - read:pets patch: description: description 2 operationId: Operation Id 2 responses: default: description: default response content: '*/*': {} security: - security_key: - write:pets - read:pets - myOauth2Security: - write:pets - security_key2: - write:pets - read:pets /completetags: get: tags: - Third Tag - Second Tag - Fourth Tag Full - Example Tag - Fifth Tag Full - Sixth Tag operationId: getTags responses: default: description: default response content: '*/*': {} /tagsinmethod: get: tags: - Third Tag - Second Tag - Fourth Tag Full operationId: getTags_1 responses: default: description: default response content: '*/*': {} /tagoperation: get: tags: - Example Tag - Second Tag operationId: getTags_2 responses: default: description: default response content: '*/*': {} components: schemas: Category: type: object properties: id: type: integer format: int64 name: type: string xml: name: Category Pet: type: object properties: id: type: integer format: int64 category: $ref: "#/components/schemas/Category" name: type: string photoUrls: type: array xml: wrapped: true items: type: string xml: name: photoUrl tags: type: array xml: wrapped: true items: $ref: "#/components/schemas/Tag" status: type: string description: pet status in the store enum: - "available,pending,sold" xml: name: Pet Tag: type: object properties: id: type: integer format: int64 name: type: string xml: name: Tag User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User SubscriptionResponse: type: object properties: subscriptionId: type: string SampleResponseSchema: type: object SecondSampleResponseSchema: type: object GenericError: type: object PetInfo: type: object properties: name: type: string securitySchemes: myOauth2Security: type: oauth2 description: myOauthSecurity Description in: header flows: implicit: authorizationUrl: http://x.com scopes: write:pets: modify pets in your account ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/OpenAPI31DefinitionResource.yaml ================================================ openapi: 3.1.0 info: title: Pet Resource Example description: API Definition summary: API Summary termsOfService: Terms of service contact: name: Fred url: http://gigantic-server.com email: Fred@gigagantic-server.com license: name: Apache 2.0 url: http://foo.bar identifier: Apache version: "2.0" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/OpenAPIDefinitionResource.yaml ================================================ openapi: 3.0.1 info: title: Pet Resource Example description: API Definition termsOfService: Terms of service contact: name: Fred url: http://gigantic-server.com email: Fred@gigagantic-server.com license: name: Apache 2.0 url: http://foo.bar version: "2.0" externalDocs: description: definition docs desc servers: - url: http://foo description: server 1 variables: var1: description: var 1 default: "1" enum: - "1" - "2" var2: description: var 2 default: "1" enum: - "1" - "2" security: - req 1: - a - b - req 2: - b - c tags: - name: Tag 1 description: desc 1 externalDocs: description: docs desc - name: Tag 2 description: desc 2 externalDocs: description: docs desc 2 - name: Tag 3 ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/SecurityResource.yaml ================================================ openapi: 3.0.1 paths: /security: get: description: description operationId: Operation Id responses: default: description: default response content: '*/*': {} security: - security_key: - write:pets - read:pets - myOauth2Security: - write:pets put: description: description 3 operationId: Operation Id 3 requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': {} security: - security_key: - write:pets - read:pets - myOauth2Security: - write:pets - security_key3: - write:pets - read:pets patch: description: description 2 operationId: Operation Id 2 responses: default: description: default response content: '*/*': {} security: - security_key: - write:pets - read:pets - myOauth2Security: - write:pets - security_key2: - write:pets - read:pets components: securitySchemes: myOauth2Security: type: oauth2 description: myOauthSecurity Description in: header flows: implicit: authorizationUrl: http://x.com scopes: write:pets: modify pets in your account ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/WebHookResource.yaml ================================================ openapi: 3.1.0 components: schemas: SubscriptionResponse: type: object properties: subscriptionId: type: string webhooks: webhook2: post: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: - integer - number format: int32 $comment: random comment $id: http://yourdomain.com/schemas/myschema.json dependentSchemas: pet: type: object patternProperties: user: type: object webhook1: post: description: "subscribes a client to updates relevant to the requestor's account,\ \ as identified by the input token. The supplied url will be used as the\ \ delivery address for response payloads" operationId: subscribe parameters: - name: subscriptionId in: path required: true style: simple schema: type: string $comment: schema $comment $id: http://yourdomain.com/schemas/myschema.json - name: explodeFalse in: query required: true schema: type: - string - number if: $ref: "#/components/schemas/SubscriptionResponse" then: $ref: "#/components/schemas/SubscriptionResponse" else: $ref: "#/components/schemas/SubscriptionResponse" $anchor: parameter $anchor $schema: parameter $schema exclusiveMaximum: 100 ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/ComplexCallback31Resource.yaml ================================================ openapi: 3.1.0 paths: /complexcallback: get: summary: Simple get operation operationId: getWithNoParameters parameters: - name: id in: query description: idParam schema: $ref: "#/components/schemas/User" responses: "200": description: voila! callbacks: testCallback1: http://www.url.com: get: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: - integer - number format: int32 $comment: random comment $id: http://yourdomain.com/schemas/myschema.json dependentSchemas: pet: type: object patternProperties: user: type: object testCallback2: http://www.url2.com: get: summary: get a review operationId: getAnSpecificReviews responses: "200": description: successful operation content: application/json: schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer format: int32 description: User Status xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/ComplexCallbackResource.yaml ================================================ openapi: 3.0.1 paths: /complexcallback: get: summary: Simple get operation operationId: getWithNoParameters parameters: - name: id in: query description: idParam schema: $ref: "#/components/schemas/User" responses: "200": description: voila! callbacks: testCallback1: http://www.url.com: get: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: integer format: int32 testCallback2: http://www.url2.com: get: summary: get a review operationId: getAnSpecificReviews responses: "200": description: successful operation content: application/json: schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/MultipleCallbacksTestWithOperationResource.yaml ================================================ openapi: 3.0.1 paths: /multiplecallback: get: summary: Simple get operation operationId: getWithNoParameters responses: "200": description: voila! callbacks: testCallback1: http://www.url.com: get: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: integer format: int32 testCallback2: http://$request.query.url: {} ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/RepeatableCallbackResource.yaml ================================================ openapi: 3.0.1 paths: /repeatablecallback: get: summary: Simple get operation operationId: getWithNoParameters responses: "200": description: voila! callbacks: testCallback: http://$requests.query.url: {} testCallback1: http://www.url.com: get: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: integer format: int32 testCallback2: http://$request.query.url: {} ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/SimpleCallbackWithOperationResource.yaml ================================================ openapi: 3.0.1 paths: /simplecallback: get: summary: Simple get operation operationId: getWithNoParameters responses: "200": description: voila! callbacks: testCallback1: http://www.url.com: get: summary: get all the reviews operationId: getAllReviews responses: "200": description: successful operation content: application/json: schema: type: integer format: int32 ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/example/ExamplesResource.yaml ================================================ openapi: 3.0.1 paths: /example: post: description: subscribes a client to updates relevant to the requestor's account operationId: subscribe parameters: - name: subscriptionId in: path required: true style: simple schema: type: string description: Schema example: Subscription example examples: subscriptionId_2: summary: Subscription number 54321 description: subscriptionId_2 value: 54321 externalValue: Subscription external value 2 subscriptionId_1: summary: Subscription number 12345 description: subscriptionId_1 value: 12345 externalValue: Subscription external value 1 example: example requestBody: description: Created user object content: '*/*': schema: type: string description: the generated UUID format: uuid readOnly: true example: Schema example examples: Default Request: summary: Subscription Request Example description: Default Request value: SubscriptionRequest externalValue: Subscription Request Value required: true responses: default: description: test description content: '*/*': schema: type: string description: the generated UUID format: uuid readOnly: true example: Schema example examples: Default Response: summary: Subscription Response Example description: Default Response value: SubscriptionResponse externalValue: Subscription Response value 1 components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User SubscriptionResponse: type: object properties: subscriptionId: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/links/LinksAndContent31Resource.yaml ================================================ openapi: 3.1.0 paths: /links: get: operationId: getUserWithAddress parameters: - name: userId in: query schema: type: string responses: default: description: test description content: '*/*': schema: type: object dependentSchemas: value: type: - string - number links: address: operationId: getAddress parameters: userId: $request.query.userId user: operationId: getUser parameters: userId: $request.query.userId x-one: x-sample-extension: "true" ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/links/LinksResource.yaml ================================================ openapi: 3.0.1 paths: /links: get: operationId: getUserWithAddress parameters: - name: userId in: query schema: type: string responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/User" links: address: operationId: getAddress parameters: userId: $request.query.userId user: operationId: getUser parameters: userId: $request.query.userId ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/operation/AnnotatedSameNameOperationResource.yaml ================================================ openapi: 3.0.1 paths: /sameOperationName: get: description: Same Operation Name operationId: getUser responses: default: description: default response content: '*/*': schema: type: string delete: description: Same Operation Name Duplicated operationId: getUser_1 requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/operation/ExternalDocumentationResource.yaml ================================================ openapi: 3.0.1 paths: /{petId}: get: summary: Find pet by ID description: Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions externalDocs: description: External Annotation Documentation url: http://url.me operationId: petId parameters: - name: petId in: path description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 responses: default: description: default response content: '*/*': {} ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/operation/FullyAnnotatedOperationResource.yaml ================================================ openapi: 3.0.1 paths: /fullyannotatedoperation/{petId}: get: summary: Find pet by ID description: Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions operationId: petId parameters: - name: petId in: path description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 responses: default: description: The pet content: '*/*': schema: $ref: "#/components/schemas/Pet" "400": description: Invalid ID supplied "404": description: Pet not found components: schemas: Category: type: object properties: id: type: integer format: int64 name: type: string xml: name: Category Tag: type: object properties: id: type: integer format: int64 name: type: string xml: name: Tag Pet: type: object properties: id: type: integer format: int64 category: $ref: "#/components/schemas/Category" name: type: string photoUrls: type: array xml: wrapped: true items: type: string xml: name: photoUrl tags: type: array xml: wrapped: true items: $ref: "#/components/schemas/Tag" status: type: string description: pet status in the store enum: - available,pending,sold xml: name: Pet ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/operation/HiddenOperationResource.yaml ================================================ openapi: 3.0.1 ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/operation/NotAnnotatedSameNameOperationResource.yaml ================================================ openapi: 3.0.1 paths: /notannotatedoperation: get: operationId: getUser responses: default: description: default response content: '*/*': schema: type: string /notannotatedoperationduplicated: get: operationId: getUser_1 requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/operation/OperationResource.yaml ================================================ openapi: 3.0.1 paths: /operationsresource2: get: operationId: getUser responses: default: description: default response content: '*/*': schema: type: string /operationsresource: get: summary: Find pet by ID description: combinatedfullyannotatedoperation/{petId} operationId: petId parameters: - name: petId in: query description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 requestBody: content: '*/*': schema: type: string responses: default: description: The pet content: '*/*': schema: $ref: "#/components/schemas/Pet" "400": description: Invalid ID supplied "404": description: Pet not found put: description: combinatedsameOperationName operationId: combinated sameOperationName responses: default: description: default response content: '*/*': schema: type: string post: operationId: getUser_1 requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: type: string head: description: combinatedsameOperationNameDuplicated operationId: combinatedsameOperationNameDuplicated requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: type: string /interfaceoperation/{petId}: get: summary: Find pet by ID Operation in SubResource description: Returns a pet in SubResource operationId: getPetById parameters: - name: petId in: path description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 responses: default: description: default response content: '*/*': {} components: schemas: Category: type: object properties: id: type: integer format: int64 name: type: string xml: name: Category Tag: type: object properties: id: type: integer format: int64 name: type: string xml: name: Tag Pet: type: object properties: id: type: integer format: int64 category: $ref: "#/components/schemas/Category" name: type: string photoUrls: type: array xml: wrapped: true items: type: string xml: name: photoUrl tags: type: array xml: wrapped: true items: $ref: "#/components/schemas/Tag" status: type: string description: pet status in the store enum: - available,pending,sold xml: name: Pet ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/operation/OperationWithoutAnnotationResource.yaml ================================================ openapi: 3.0.1 paths: /operationwithouannotation: get: operationId: getUser responses: default: description: default response content: '*/*': schema: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/operation/ServerOperationResource.yaml ================================================ openapi: 3.0.1 servers: - url: http://foo description: server 1 paths: /serversoperation: get: description: Pets Example operationId: Pets responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/Pet" servers: - url: http://foo2 description: server 2 components: schemas: Category: type: object properties: id: type: integer format: int64 name: type: string xml: name: Category Tag: type: object properties: id: type: integer format: int64 name: type: string xml: name: Tag Pet: type: object properties: id: type: integer format: int64 category: $ref: "#/components/schemas/Category" name: type: string photoUrls: type: array xml: wrapped: true items: type: string xml: name: photoUrl tags: type: array xml: wrapped: true items: $ref: "#/components/schemas/Tag" status: type: string description: pet status in the store enum: - available,pending,sold xml: name: Pet ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/operation/SubResource.yaml ================================================ openapi: 3.0.1 paths: /interfaceoperation/{petId}: get: summary: Find pet by ID Operation in SubResource description: Returns a pet in SubResource operationId: getPetById parameters: - name: petId in: path description: ID of pet that needs to be fetched required: true schema: type: integer format: int64 responses: default: description: default response content: '*/*': {} ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/ArraySchemaResource.yaml ================================================ openapi: 3.0.1 paths: /arrayschema: post: description: subscribes a client to updates relevant to the requestor's account, as identified by the input token. The supplied url will be used as the delivery address for response payloads operationId: subscribe parameters: - name: arrayParameter in: query required: true explode: true schema: maxItems: 10 minItems: 1 uniqueItems: true type: array items: $ref: "#/components/schemas/SubscriptionResponse" responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/SubscriptionResponse" components: schemas: SubscriptionResponse: type: object properties: subscriptionId: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/ComplexParameterResource.yaml ================================================ openapi: 3.0.1 paths: /complexparameter: get: operationId: create User parameters: - name: id in: query description: idParam schema: type: string - name: lastName in: query schema: type: string - name: address in: query description: address schema: $ref: "#/components/schemas/User" requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/ComplexParameterWithOperationResource.yaml ================================================ openapi: 3.0.1 paths: /complexparameter: get: operationId: create User parameters: - name: phone in: path description: Phone required: true schema: type: string - name: id in: query description: idParam schema: type: string - name: lastName in: query schema: type: string - name: address in: query description: address schema: $ref: "#/components/schemas/User" requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/MultipleNotAnnotatedParameter.yaml ================================================ openapi: 3.0.1 paths: /multiplenoannotatedparameter: post: operationId: create User requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': {} ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/OpenAPIJaxRSAnnotatedParameter.yaml ================================================ openapi: 3.0.1 paths: /openapijaxrsannotatedparameter: get: operationId: create User parameters: - name: id in: query description: idParam schema: type: string responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/OpenAPIWithContentJaxRSAnnotatedParameter.yaml ================================================ openapi: 3.0.1 paths: /openapiwithcontentjaxrsannotatedparameter: get: operationId: create User parameters: - name: id in: query description: idParam content: '*/*': schema: type: string description: Id Schema Definition responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/OpenAPIWithImplementationJaxRSAnnotatedParameter.yaml ================================================ openapi: 3.0.1 paths: /openapiwithimplementationjaxrsannotatedparameter: get: operationId: create User parameters: - name: id in: query description: idParam schema: $ref: "#/components/schemas/User" responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/Parameters31Resource.yaml ================================================ openapi: 3.1.0 paths: /parameters: post: description: "subscribes a client to updates relevant to the requestor's account,\ \ as identified by the input token. The supplied url will be used as the\ \ delivery address for response payloads" operationId: subscribe parameters: - name: subscriptionId in: path required: true style: simple schema: type: string $comment: schema $comment $id: http://yourdomain.com/schemas/myschema.json - name: explodeFalse in: query required: true schema: type: - string - number if: $ref: "#/components/schemas/SubscriptionResponse" then: $ref: "#/components/schemas/SubscriptionResponse" else: $ref: "#/components/schemas/SubscriptionResponse" $anchor: parameter $anchor $schema: parameter $schema exclusiveMaximum: 100 - name: explodeAvoiding in: query required: true schema: type: string format: id description: the generated id exclusiveMaximum: 1000 exclusiveMinimum: 10 readOnly: true - name: arrayParameter in: query required: true explode: true content: application/json: schema: type: number description: the generated id readOnly: true application/xml: schema: type: number description: the generated id readOnly: true - name: arrayParameterImplementation in: query required: true explode: true schema: type: array contains: {} items: $ref: "#/components/schemas/SubscriptionResponse" maxContains: 50 maxItems: 10 minContains: 1 minItems: 1 unevaluatedItems: {} uniqueItems: true - name: arrayParameterImplementation2 in: query required: true explode: true schema: $ref: "#/components/schemas/SubscriptionResponse" - name: id in: query description: idParam schema: type: string responses: default: description: test description content: '*/*': schema: $id: http://yourdomain.com/schemas/myschema.json dependentSchemas: pet: $ref: "#/components/schemas/Pet" patternProperties: user: $ref: "#/components/schemas/User" properties: extraObject: type: object components: schemas: Category: type: object properties: id: type: integer format: int64 name: type: string xml: name: Category Pet: type: object properties: id: type: integer format: int64 category: $ref: "#/components/schemas/Category" name: type: string photoUrls: type: array items: type: string xml: name: photoUrl xml: wrapped: true tags: type: array items: $ref: "#/components/schemas/Tag" xml: wrapped: true status: type: string description: pet status in the store enum: - "available,pending,sold" xml: name: Pet Tag: type: object properties: id: type: integer format: int64 name: type: string xml: name: tag User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer format: int32 description: User Status xml: name: User SubscriptionResponse: type: object properties: subscriptionId: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/ParametersResource.yaml ================================================ openapi: 3.0.1 paths: /parameters: post: description: subscribes a client to updates relevant to the requestor's account, as identified by the input token. The supplied url will be used as the delivery address for response payloads operationId: subscribe parameters: - name: subscriptionId in: path required: true style: simple schema: $ref: "#/components/schemas/SubscriptionResponse" - name: formId in: query required: true schema: type: string example: Example - name: explodeFalse in: query required: true explode: false schema: $ref: "#/components/schemas/SubscriptionResponse" - name: explodeTrue in: query required: true explode: true schema: $ref: "#/components/schemas/SubscriptionResponse" - name: explodeAvoiding in: query required: true schema: type: string description: the generated id format: id readOnly: true - name: arrayParameter in: query required: true explode: true content: application/json: schema: type: number description: the generated id readOnly: true application/xml: schema: type: number description: the generated id readOnly: true - name: arrayParameterImplementation in: query required: true explode: true schema: maxItems: 10 minItems: 1 uniqueItems: true type: array items: $ref: "#/components/schemas/SubscriptionResponse" - name: arrayParameterImplementation2 in: query required: true explode: true schema: $ref: "#/components/schemas/SubscriptionResponse" - name: id in: query description: idParam schema: type: string responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/SubscriptionResponse" components: schemas: SubscriptionResponse: type: object properties: subscriptionId: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/RepeatableParametersResource.yaml ================================================ openapi: 3.0.1 paths: /repeatableparameter: post: description: subscribes a client to updates relevant to the requestor's account, as identified by the input token. The supplied url will be used as the delivery address for response payloads operationId: subscribe parameters: - name: subscriptionId in: path required: true style: simple schema: $ref: "#/components/schemas/SubscriptionResponse" - name: formId in: query required: true schema: type: string example: Example - name: explodeFalse in: query required: true explode: false schema: $ref: "#/components/schemas/SubscriptionResponse" - name: explodeTrue in: query required: true explode: true schema: $ref: "#/components/schemas/SubscriptionResponse" - name: explodeAvoiding in: query required: true schema: type: string description: the generated id format: id readOnly: true - name: arrayParameter in: query required: true explode: true content: application/json: schema: type: number description: the generated id readOnly: true application/xml: schema: type: number description: the generated id readOnly: true - name: arrayParameterImplementation in: query required: true explode: true schema: maxItems: 10 minItems: 1 uniqueItems: true type: array items: $ref: "#/components/schemas/SubscriptionResponse" - name: arrayParameterImplementation2 in: query required: true explode: true schema: $ref: "#/components/schemas/SubscriptionResponse" responses: default: description: test description content: '*/*': schema: $ref: "#/components/schemas/SubscriptionResponse" components: schemas: SubscriptionResponse: type: object properties: subscriptionId: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/SingleJaxRSAnnotatedParameter.yaml ================================================ openapi: 3.0.1 paths: /singlejaxrsannotatedparameter: get: operationId: create User parameters: - name: id in: query schema: type: string responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/parameters/SingleNotAnnotatedParameter.yaml ================================================ openapi: 3.0.1 paths: /singlenoannotatedparameter: get: operationId: create User requestBody: content: '*/*': schema: type: string responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/requestbody/RequestBody31Resource.yaml ================================================ openapi: 3.1.0 paths: /methodWithRequestBodyAndTwoParameters: post: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyAndTwoParameters parameters: - name: name in: query schema: type: string - name: code in: query schema: type: string requestBody: description: Created user object content: '*/*': schema: $ref: "#/components/schemas/User" required: true responses: default: description: default response content: '*/*': {} /methodWithRequestBodyWithoutContentWithoutImplementation: get: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyWithoutContentWithoutImplementation requestBody: description: Created user object content: '*/*': schema: type: - string - number - object if: type: object then: type: object else: type: object $anchor: parameter $anchor $schema: parameter $schema description: User description example: User Description exclusiveMaximum: 100 exclusiveMinimum: 1 unevaluatedProperties: type: object required: true responses: default: description: default response content: '*/*': {} components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer format: int32 description: User Status xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/requestbody/RequestBodyMethodPriorityResource.yaml ================================================ openapi: 3.0.1 paths: /requestbodymethodpriority: post: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyAndTwoParameters requestBody: description: Created user object on Method content: '*/*': schema: $ref: "#/components/schemas/User" required: true responses: default: description: default response content: '*/*': {} components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/requestbody/RequestBodyParameterPriorityResource.yaml ================================================ openapi: 3.0.1 paths: /requestbodyparameterpriority: post: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyAndTwoParameters requestBody: description: Created user object inside Parameter content: '*/*': schema: $ref: "#/components/schemas/User" required: true responses: default: description: default response content: '*/*': {} components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/requestbody/RequestBodyResource.yaml ================================================ openapi: 3.0.1 paths: /methodWithRequestBodyWithoutContent: get: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyWithoutContent requestBody: description: Created user object content: '*/*': schema: $ref: "#/components/schemas/User" required: true responses: default: description: default response content: '*/*': {} /methodWithRequestBodyWithoutContentWithoutImplementation: get: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyWithoutContentWithoutImplementation requestBody: description: Created user object content: '*/*': schema: type: string description: User description example: User Description required: true responses: default: description: default response content: '*/*': {} /methodWithRequestBodyWithoutAnnotation: put: summary: Modify user description: Modifying user. operationId: methodWithRequestBodyWithoutAnnotation requestBody: content: '*/*': schema: $ref: "#/components/schemas/User" responses: default: description: default response content: '*/*': {} /methodWithoutRequestBodyAndTwoParameters: delete: summary: Delete user description: This can only be done by the logged in user. operationId: methodWithoutRequestBodyAndTwoParameters parameters: - name: name in: query schema: type: string - name: code in: query schema: type: string responses: default: description: default response content: '*/*': {} /methodWithRequestBodyWithoutAnnotationAndTwoConsumes: put: summary: Modify pet description: Modifying pet. operationId: methodWithRequestBodyWithoutAnnotationAndTwoConsumes requestBody: content: application/json: schema: $ref: "#/components/schemas/User" application/xml: schema: $ref: "#/components/schemas/User" responses: default: description: default response content: '*/*': {} /methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes: post: summary: Create pet description: Creating pet. operationId: methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes requestBody: content: application/json: schema: $ref: "#/components/schemas/Pet" application/xml: schema: $ref: "#/components/schemas/Pet" responses: default: description: default response content: '*/*': {} /methodWithTwoRequestBodyWithAnnotationAndTwoConsumes: post: summary: Create pet description: Creating pet. operationId: methodWithTwoRequestBodyWithAnnotationAndTwoConsumes requestBody: description: Request Body User content: application/json: schema: $ref: "#/components/schemas/User" application/xml: schema: $ref: "#/components/schemas/User" responses: default: description: default response content: '*/*': {} /methodWithOneSimpleRequestBody: delete: summary: Delete pet description: Deleting pet. operationId: methodWithOneSimpleRequestBody requestBody: content: application/json: schema: type: integer format: int32 application/xml: schema: type: integer format: int32 responses: default: description: default response content: '*/*': {} /methodWithRequestBodyAndTwoParameters: post: summary: Create user description: This can only be done by the logged in user. operationId: methodWithRequestBodyAndTwoParameters parameters: - name: name in: query schema: type: string - name: code in: query schema: type: string requestBody: description: Created user object content: '*/*': schema: $ref: "#/components/schemas/User" required: true responses: default: description: default response content: '*/*': {} components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User Category: type: object properties: id: type: integer format: int64 name: type: string xml: name: Category Tag: type: object properties: id: type: integer format: int64 name: type: string xml: name: Tag Pet: type: object properties: id: type: integer format: int64 category: $ref: "#/components/schemas/Category" name: type: string photoUrls: type: array xml: wrapped: true items: type: string xml: name: photoUrl tags: type: array xml: wrapped: true items: $ref: "#/components/schemas/Tag" status: type: string description: pet status in the store enum: - available,pending,sold xml: name: Pet ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/responses/ComplexResponseResource.yaml ================================================ openapi: 3.0.1 paths: /complexresponse: get: summary: Find pets description: Returns the Pets operationId: getPets responses: "200": description: Response inside Operation content: '*/*': schema: $ref: "#/components/schemas/Pet" default: description: Default Pet content: '*/*': schema: type: string description: Default Pet example: New Pet "404": description: Couldn't find pet components: schemas: Category: type: object properties: id: type: integer format: int64 name: type: string xml: name: Category Tag: type: object properties: id: type: integer format: int64 name: type: string xml: name: Tag Pet: type: object properties: id: type: integer format: int64 category: $ref: "#/components/schemas/Category" name: type: string photoUrls: type: array xml: wrapped: true items: type: string xml: name: photoUrl tags: type: array xml: wrapped: true items: $ref: "#/components/schemas/Tag" status: type: string description: pet status in the store enum: - available,pending,sold xml: name: Pet ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/responses/ImplementationResponseResource.yaml ================================================ openapi: 3.0.1 paths: /implementationresponse: get: summary: Simple get operation description: Defines a simple get operation with no inputs and a complex output object operationId: getWithPayloadResponse responses: "200": description: voila! content: application/json: schema: $ref: "#/components/schemas/SecondSampleResponseSchema" "400": description: boo content: '*/*': schema: $ref: "#/components/schemas/GenericError" deprecated: true components: schemas: SecondSampleResponseSchema: type: object GenericError: type: object SampleResponseSchema: type: object ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/responses/MethodArrayResponseResource.yaml ================================================ openapi: 3.1.0 paths: /arrayresponseinmethod: get: operationId: arrayResponseWithTypeImplementation responses: default: content: '*/*': schema: type: array description: Array description items: $ref: "#/components/schemas/PetInfo" description: Item description components: schemas: PetInfo: type: object properties: name: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/responses/MethodResponseResource.yaml ================================================ openapi: 3.0.1 paths: /responseinmethod: get: summary: Find pets description: Returns the Pets operationId: getPets responses: "200": description: Status OK ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/responses/NoImplementationResponseResource.yaml ================================================ openapi: 3.0.1 paths: /noimplementationresponseresource: get: operationId: getUser parameters: - name: userId in: query schema: type: string responses: "400": description: test description links: user: operationId: getUser parameters: userId: $request.query.userId "200": description: 200 description links: pet: operationId: getUser parameters: userId: $request.query.userId components: schemas: User: type: object properties: id: type: string username: type: string ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/responses/NoResponseResource.yaml ================================================ openapi: 3.0.1 paths: /noresponse: get: summary: Find pets description: Returns the Pets operationId: getPets responses: default: description: default response content: '*/*': schema: $ref: "#/components/schemas/User" components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string lastName: type: string email: type: string password: type: string phone: type: string userStatus: type: integer description: User Status format: int32 xml: name: User ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/responses/OperationResponseResource.yaml ================================================ openapi: 3.0.1 paths: /responseinoperation: get: summary: Find Users description: Returns the Users operationId: getUsers responses: "200": description: Status OK ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/responses/PriorityResponseResource.yaml ================================================ openapi: 3.0.1 paths: /priorityresponses: get: summary: Find pets description: Returns the Pets operationId: getPets responses: "200": description: Inside Method Operation ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/tags/CompleteTagResource.yaml ================================================ openapi: 3.0.1 tags: - name: Definition First Tag - name: Definition Second Tag full description: desc definition - name: Fourth Tag Full description: desc externalDocs: description: docs desc - name: Fifth Tag Full description: desc class externalDocs: description: docs desc class paths: /completetags: get: tags: - Third Tag - Second Tag - Fourth Tag Full - Example Tag - Fifth Tag Full - Sixth Tag operationId: getTags responses: default: description: default response content: '*/*': {} ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/tags/TagClassResource.yaml ================================================ openapi: 3.0.1 tags: - name: Fourth Tag Full description: desc class externalDocs: description: docs desc class - name: Fifth Tag Full description: desc class externalDocs: description: docs desc class ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/tags/TagMethodResource.yaml ================================================ openapi: 3.0.1 tags: - name: Fourth Tag Full description: desc externalDocs: description: docs desc paths: /tagsinmethod: get: tags: - Third Tag - Second Tag - Fourth Tag Full operationId: getTags responses: default: description: default response content: '*/*': {} ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/tags/TagOpenAPIDefinitionResource.yaml ================================================ openapi: 3.0.1 tags: - name: Definition First Tag - name: Definition Second Tag full description: desc definition ================================================ FILE: modules/swagger-jaxrs2/src/test/resources/petstore/tags/TagOperationResource.yaml ================================================ openapi: 3.0.1 paths: /tagoperation: get: tags: - Example Tag - Second Tag operationId: getTags responses: default: description: default response content: '*/*': {} ================================================ FILE: modules/swagger-jaxrs2/src/test/webapp/WEB-INF/web.xml ================================================ jersey org.glassfish.jersey.servlet.ServletContainer jersey.config.server.wadl.disableWadl true jersey.config.server.provider.packages io.swagger.v3.jaxrs2.integration.resources,io.swagger.v3.jaxrs2.it.resources openApi.configuration.prettyPrint true jersey.config.server.provider.classnames org.glassfish.jersey.media.multipart.MultiPartFeature 1 oas io.swagger.v3.jaxrs2.integration.OpenApiServlet jersey.config.server.wadl.disableWadl true jersey.config.server.provider.packages io.swagger.v3.jaxrs2.integration.resources,io.swagger.v3.jaxrs2.it.resources openApi.configuration.prettyPrint true openApi.configuration.openAPI31 true openApi.configuration.convertToOpenAPI31 true bootstrap io.swagger.v3.jaxrs2.BootstrapServlet jersey /* oas /oas/* bootstrap /bootstrap ================================================ FILE: modules/swagger-jaxrs2-servlet-initializer/pom.xml ================================================ swagger-project io.swagger.core.v3 2.2.46-SNAPSHOT ../../ 4.0.0 swagger-jaxrs2-servlet-initializer swagger-jaxrs2-servlet-initializer swagger-servlet-initializer src/main/java install src/test/resources biz.aQute.bnd bnd-maven-plugin Export-Package: io.swagger.v3.jaxrs2.integration org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF io.swagger.v3.jaxrs2.integration org.codehaus.mojo build-helper-maven-plugin 3.5.0 jetty.port jetty.port.stop reserve-port pre-integration-test reserve-network-port org.apache.maven.plugins maven-failsafe-plugin ${failsafe-plugin-version} integration-test verify ${jetty.port} org.eclipse.jetty jetty-maven-plugin 10 ${jetty.port} a ${jetty.port.stop} true ${project.basedir}/src/test/webapp io.swagger.core.v3 swagger-jaxrs2 ${project.version} start-jetty pre-integration-test start 0 stop-jetty post-integration-test stop jakarta.ws.rs jakarta.ws.rs-api provided jakarta.servlet jakarta.servlet-api provided ch.qos.logback logback-classic provided ch.qos.logback logback-core provided io.swagger.core.v3 swagger-jaxrs2 ${project.version} provided org.testng testng test io.rest-assured rest-assured test javax.xml.bind jaxb-api org.apache.httpcomponents httpmime org.mockito mockito-core test org.glassfish.jersey.core jersey-server ${jersey2-version} test org.javassist javassist ================================================ FILE: modules/swagger-jaxrs2-servlet-initializer/src/main/java/io/swagger/v3/jaxrs2/integration/SwaggerServletInitializer.java ================================================ package io.swagger.v3.jaxrs2.integration; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Webhooks; import io.swagger.v3.oas.integration.IgnoredPackages; import io.swagger.v3.oas.integration.OpenApiConfigurationException; import io.swagger.v3.oas.integration.SwaggerConfiguration; import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.HandlesTypes; import javax.ws.rs.ApplicationPath; import javax.ws.rs.Path; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Collectors; /** * deprecated since 2.1.2. Please use io.swagger.v3.jaxrs2.integration.SwaggerServletInitializer in * swagger-jaxrs2-servlet-initializer-v2 */ @Deprecated @HandlesTypes({Path.class, OpenAPIDefinition.class, ApplicationPath.class, Webhooks.class}) public class SwaggerServletInitializer implements ServletContainerInitializer { static final Set ignored = new HashSet(); static { ignored.addAll(IgnoredPackages.ignored); } public SwaggerServletInitializer() { } @Override public void onStartup(Set> classes, ServletContext servletContext) throws ServletException { if (classes != null && ! classes.isEmpty()) { Set> resources = new LinkedHashSet(); classes.stream() .filter(c -> ignored.stream().noneMatch(i -> c.getName().startsWith(i))) .forEach(resources::add); if (!resources.isEmpty()) { // init context try { SwaggerConfiguration oasConfig = new SwaggerConfiguration() .resourceClasses(resources.stream().map(Class::getName).collect(Collectors.toSet())); new JaxrsOpenApiContextBuilder() .openApiConfiguration(oasConfig) .buildContext(true); } catch (OpenApiConfigurationException e) { throw new RuntimeException(e.getMessage(), e); } } } } } ================================================ FILE: modules/swagger-jaxrs2-servlet-initializer/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer ================================================ io.swagger.v3.jaxrs2.integration.SwaggerServletInitializer ================================================ FILE: modules/swagger-jaxrs2-servlet-initializer-v2/pom.xml ================================================ swagger-project io.swagger.core.v3 2.2.46-SNAPSHOT ../../ 4.0.0 swagger-jaxrs2-servlet-initializer-v2 swagger-jaxrs2-servlet-initializer-v2 swagger-servlet-initializer-v2 src/main/java install src/test/resources biz.aQute.bnd bnd-maven-plugin org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF io.swagger.v3.jaxrs2.integration.servlet org.codehaus.mojo build-helper-maven-plugin 3.5.0 jetty.port jetty.port.stop reserve-port pre-integration-test reserve-network-port org.apache.maven.plugins maven-failsafe-plugin ${failsafe-plugin-version} integration-test verify ${jetty.port} org.eclipse.jetty jetty-maven-plugin 10 ${jetty.port} a ${jetty.port.stop} true ${project.basedir}/src/test/webapp io.swagger.core.v3 swagger-jaxrs2 ${project.version} start-jetty pre-integration-test start 0 stop-jetty post-integration-test stop jakarta.ws.rs jakarta.ws.rs-api provided jakarta.servlet jakarta.servlet-api provided ch.qos.logback logback-classic provided ch.qos.logback logback-core provided io.swagger.core.v3 swagger-jaxrs2 ${project.version} provided org.testng testng test io.rest-assured rest-assured test javax.xml.bind jaxb-api org.apache.httpcomponents httpmime org.mockito mockito-core test org.glassfish.jersey.core jersey-server ${jersey2-version} test org.javassist javassist ================================================ FILE: modules/swagger-jaxrs2-servlet-initializer-v2/src/main/java/io/swagger/v3/jaxrs2/integration/servlet/SwaggerServletInitializer.java ================================================ package io.swagger.v3.jaxrs2.integration.servlet; import io.swagger.v3.jaxrs2.integration.JaxrsOpenApiContextBuilder; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Webhooks; import io.swagger.v3.oas.integration.IgnoredPackages; import io.swagger.v3.oas.integration.OpenApiConfigurationException; import io.swagger.v3.oas.integration.SwaggerConfiguration; import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.HandlesTypes; import javax.ws.rs.ApplicationPath; import javax.ws.rs.Path; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Collectors; /** * * @since 2.1.2 */ @HandlesTypes({Path.class, OpenAPIDefinition.class, ApplicationPath.class, Webhooks.class}) public class SwaggerServletInitializer implements ServletContainerInitializer { static final Set ignored = new HashSet(); static { ignored.addAll(IgnoredPackages.ignored); } public SwaggerServletInitializer() { } @Override public void onStartup(Set> classes, ServletContext servletContext) throws ServletException { if (classes != null && ! classes.isEmpty()) { Set> resources = new LinkedHashSet(); classes.stream() .filter(c -> ignored.stream().noneMatch(i -> c.getName().startsWith(i))) .forEach(resources::add); if (!resources.isEmpty()) { // init context try { SwaggerConfiguration oasConfig = new SwaggerConfiguration() .resourceClasses(resources.stream().map(Class::getName).collect(Collectors.toSet())); new JaxrsOpenApiContextBuilder() .openApiConfiguration(oasConfig) .buildContext(true); } catch (OpenApiConfigurationException e) { throw new RuntimeException(e.getMessage(), e); } } } } } ================================================ FILE: modules/swagger-jaxrs2-servlet-initializer-v2/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer ================================================ io.swagger.v3.jaxrs2.integration.servlet.SwaggerServletInitializer ================================================ FILE: modules/swagger-maven-plugin/README.md ================================================ # swagger-maven-plugin * Resolves project openAPI specification and saves the result in JSON, YAML or both formats. All parameters except `outputFileName`, `outputFormat`, `skip`, `encoding` and `outputPath` correspond to `swagger` [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties) with same name. ## Jakarta namespace support Since version 2.1.7 Swagger Core supports also Jakarta namespace, with a parallel set of artifacts with `-jakarta` suffix, providing the same functionality as the "standard" `javax` namespace ones. Please check [Wiki](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Getting-started) for more details Both `javax` and `jakarta` examples are provided below ## Configuration example ### `javax` namespace ```xml io.swagger.core.v3 swagger-maven-plugin 2.2.45 openapi ${project.build.directory}/generatedtest JSONANDYAML test.petstore TRUE compile resolve io.swagger.core.v3 swagger-jaxrs2 2.2.45 javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1.0 ``` ### `jakarta` namespace ```xml io.swagger.core.v3 swagger-maven-plugin-jakarta 2.2.45 openapi ${project.build.directory}/generatedtest JSONANDYAML test.petstore TRUE compile resolve io.swagger.core.v3 swagger-jaxrs2-jakarta 2.2.45 jakarta.ws.rs jakarta.ws.rs-api 3.0.0 jakarta.servlet jakarta.servlet-api 5.0.0 ``` ## Configuration example with provided Swagger configuration file ### `javax` namespace ```xml io.swagger.core.v3 swagger-maven-plugin 2.2.45 openapi ${project.build.directory}/generatedtest ${project.basedir}/src/main/resources/configurationFile.yaml compile resolve ... ``` ### `jakarta` namespace ```xml io.swagger.core.v3 swagger-maven-plugin-jakarta 2.2.45 openapi ${project.build.directory}/generatedtest ${project.basedir}/src/main/resources/configurationFile.yaml compile resolve ... ``` #### Parameters Parameter | Description | Required | Default --------- | ----------- |---------------| ------- `outputPath`|output path where file(s) are saved| true | `outputFileName`|file name (no extension)| false |`openapi` `outputFormat`|file format (`JSON`, `YAML`, `JSONANDYAML`| false |`JSON` `skip`|if `TRUE` skip execution| false |`FALSE` `encoding`|encoding of output file(s)| false | `resourcePackages`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `resourceClasses`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `prettyPrint`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |`TRUE` `sortOutput`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |`FALSE` `alwaysResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |`FALSE` `skipResolveAppPath`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |`FALSE` `openapiFilePath`|path to openapi file to be merged with resolved specification, see [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `configurationFilePath`|path to swagger config file to be merged with resolved specification, see [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration)| false | `filterClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `readerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `scannerClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `readAllResources`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `ignoredRoutes`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `objectMapperProcessorClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `defaultResponseCode`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `groupsValidationStrategy`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `validatorProcessorClass`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)|false| `modelConverterClasses`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `contextId`|see [Context](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#context)| false |${project.artifactId} `openapi31`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false | `schemaResolution`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| DEFAULT | `openAPIVersion`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| `3.0.1/3.1.0` | *** Since version 2.0.8, `configurationFilePath` parameter is available, allowing to specify a path to a [swagger configuration file](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration); If single maven configuration parameters (e.g. `prettyPrint`) are also defined, these will overwrite any value set in configuration file; the same applies to `openapiFilePath` which takes precedence over `openAPI` field in configuration file. Since version 2.1.6, `sortOutput` parameter is available, allowing to sort object properties and map keys alphabetically. Since version 2.1.6, `objectMapperProcessorClass` allows to configure also the ObjectMapper instance used to serialize the resolved OpenAPI Since version 2.1.9, `alwaysResolveAppPath` parameter is available, allowing to trigger resolving of Application Path from annotation also not in runtime (e.g. using servlet in separate application, or in maven plugin at build time, etc) Since version 2.2.12, `openapi31` parameter is available, if set to true the resolved spec will be processed into a 3.1.0 specification by resolving according to OAS 3.1 rules Since version 2.1.15, `skipResolveAppPath` parameter is available, allowing to skip resolving of Application Path from annotation Since version 2.2.17, `defaultResponseCode` parameter is available, allowing to set the code used when resolving responses with no http status code annotation Since version 2.2.24, `schemaResolution` parameter is available, allowing to specify how object schemas and object properties within schemas are resolved for OAS 3.0 specification Since version 2.2.28, `openAPIVersion` parameter is available, allowing to specify the version of the OpenAPI specification to be used for the resolved spec. Since version 2.2.29, `groupsValidationStrategy` parameter is available, allowing to specify the strategy for resolving Validation annotations (`never`, `always`, `neverIfNoContext`). Since version 2.2.29, `validatorProcessorClass` parameter is available, allowing to specify a custom validator processor class, implementation of `io.swagger.v3.core.util.ValidatorProcessor`. ================================================ FILE: modules/swagger-maven-plugin/pom.xml ================================================ io.swagger.core.v3 swagger-project 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-maven-plugin maven-plugin swagger-maven-plugin swagger-maven-plugin org.codehaus.plexus plexus-component-metadata 2.1.1 generate-metadata org.apache.maven.plugins maven-plugin-plugin 3.7.0 io.swagger.core.v3 swagger-eclipse-transformer-maven-plugin ${project.version} false jakarta ${project.basedir}/../swagger-project-jakarta/modules/${project.artifactId}-jakarta/transformed transform-jakarta run package org.apache.maven maven-plugin-api ${maven.version} provided org.codehaus.plexus plexus-utils org.codehaus.plexus plexus-component-annotations org.codehaus.plexus plexus-classworlds org.apache.maven maven-core ${maven.version} provided org.codehaus.plexus plexus-utils org.apache.maven.plugin-tools maven-plugin-annotations 3.15.1 provided org.apache.maven maven-artifact org.codehaus.plexus plexus-archiver 4.10.0 test org.codehaus.plexus plexus-utils org.apache.commons commons-compress org.apache.maven.plugin-testing maven-plugin-testing-harness 3.3.0 test junit junit org.codehaus.plexus plexus-utils org.codehaus.plexus plexus-component-annotations org.codehaus.plexus plexus-archiver org.apache.commons commons-lang3 ${commons-lang-version} org.codehaus.plexus plexus-utils 3.6.0 org.codehaus.plexus plexus-component-annotations 2.2.0 io.swagger.core.v3 swagger-jaxrs2 ${project.version} junit junit ${junit.version} test org.apache.maven maven-compat ${maven.version} test org.codehaus.plexus plexus-utils com.github.tomakehurst wiremock 2.27.2 test com.jayway.jsonpath json-path org.eclipse.jetty jetty-server org.eclipse.jetty jetty-servlet org.eclipse.jetty jetty-servlets org.eclipse.jetty jetty-webapp org.eclipse.jetty jetty-proxy commons-codec commons-codec com.github.jknack handlebars-helpers com.github.jknack handlebars org.apache.commons commons-compress ${commons-compress-version} test org.eclipse.jetty jetty-server ${wiremock-jetty-version} test org.eclipse.jetty jetty-servlet ${wiremock-jetty-version} test org.eclipse.jetty jetty-servlets ${wiremock-jetty-version} test org.eclipse.jetty jetty-webapp ${wiremock-jetty-version} test org.eclipse.jetty jetty-proxy ${wiremock-jetty-version} test ch.qos.logback logback-classic test ch.qos.logback logback-core test jakarta.ws.rs jakarta.ws.rs-api test com.github.jknack handlebars-helpers test 4.4.0 com.github.jknack handlebars test 4.4.0 UTF-8 3.9.9 4.13.2 9.4.57.v20241219 1.27.1 ================================================ FILE: modules/swagger-maven-plugin/src/main/java/io/swagger/v3/plugin/maven/IncludeProjectDependenciesComponentConfigurator.java ================================================ package io.swagger.v3.plugin.maven; import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.configurator.AbstractComponentConfigurator; import org.codehaus.plexus.component.configurator.ComponentConfigurationException; import org.codehaus.plexus.component.configurator.ComponentConfigurator; import org.codehaus.plexus.component.configurator.ConfigurationListener; import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.codehaus.plexus.configuration.PlexusConfiguration; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; /* * Thanks to original post by Brian Jackson (http://jaxzin.github.io/) http://maven.40175.n5.nabble.com/Adding-project-dependencies-and-generated-classes-to-classpath-of-my-plugin-tp110119p110121.html */ @Component(role = ComponentConfigurator.class, hint = "include-project-dependencies") public class IncludeProjectDependenciesComponentConfigurator extends AbstractComponentConfigurator { @Override public void configureComponent(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator, ClassRealm containerRealm, ConfigurationListener listener) throws ComponentConfigurationException { addProjectDependenciesToClassRealm(expressionEvaluator, containerRealm); ObjectWithFieldsConverter converter = new ObjectWithFieldsConverter(); converter.processConfiguration(converterLookup, component, containerRealm, configuration, expressionEvaluator, listener); } private void addProjectDependenciesToClassRealm(ExpressionEvaluator expressionEvaluator, ClassRealm containerRealm) throws ComponentConfigurationException { List compileClasspathElements; try { @SuppressWarnings("unchecked") List evaluated = (List) expressionEvaluator.evaluate("${project.compileClasspathElements}"); compileClasspathElements = evaluated; } catch (ExpressionEvaluationException e) { throw new ComponentConfigurationException("There was a problem evaluating: ${project.compileClasspathElements}", e); } // Add the project dependencies to the ClassRealm final URL[] urls = buildURLs(compileClasspathElements); for (URL url : urls) { containerRealm.addURL(url); } } private URL[] buildURLs(List runtimeClasspathElements) throws ComponentConfigurationException { // Add the projects classes and dependencies List urls = new ArrayList<>(runtimeClasspathElements.size()); for (String element : runtimeClasspathElements) { try { final URL url = new File(element).toURI().toURL(); urls.add(url); } catch (MalformedURLException e) { throw new ComponentConfigurationException("Unable to access project dependency: " + element, e); } } // Add the plugin's dependencies (so Trove stuff works if Trove isn't on return urls.toArray(new URL[urls.size()]); } } ================================================ FILE: modules/swagger-maven-plugin/src/main/java/io/swagger/v3/plugin/maven/SwaggerMojo.java ================================================ package io.swagger.v3.plugin.maven; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import io.swagger.v3.core.filter.OpenAPISpecFilter; import io.swagger.v3.core.filter.SpecFilter; import io.swagger.v3.core.util.Configuration; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.jaxrs2.integration.JaxrsOpenApiContextBuilder; import io.swagger.v3.oas.integration.GenericOpenApiContextBuilder; import io.swagger.v3.oas.integration.OpenApiConfigurationException; import io.swagger.v3.oas.integration.SwaggerConfiguration; import io.swagger.v3.oas.integration.api.OpenApiContext; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.StringUtils; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.function.BiFunction; import static java.lang.String.format; @Mojo( name = "resolve", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, defaultPhase = LifecyclePhase.COMPILE, threadSafe = true, configurator = "include-project-dependencies" ) public class SwaggerMojo extends AbstractMojo { public enum Format {JSON, YAML, JSONANDYAML} @Override public void execute() throws MojoExecutionException, MojoFailureException { if (skip) { getLog().info( "Skipping OpenAPI specification resolution" ); return; } getLog().info( "Resolving OpenAPI specification.." ); if (project != null) { String pEnc = project.getProperties().getProperty("project.build.sourceEncoding"); if (StringUtils.isNotBlank(pEnc)) { projectEncoding = pEnc; } } if (StringUtils.isBlank(encoding)) { encoding = projectEncoding; } // read swagger configuration if one was provided Optional swaggerConfiguration = readStructuredDataFromFile(configurationFilePath, SwaggerConfiguration.class, "configurationFilePath"); // read openApi config, if one was provided Optional openAPIInput = readStructuredDataFromFile(openapiFilePath, OpenAPI.class, "openapiFilePath"); config = mergeConfig(openAPIInput.orElse(null), swaggerConfiguration.orElse(new SwaggerConfiguration())); setDefaultsIfMissing(config); try { GenericOpenApiContextBuilder builder = new JaxrsOpenApiContextBuilder() .openApiConfiguration(config); if (StringUtils.isNotBlank(contextId)) { builder.ctxId(contextId); } OpenApiContext context = builder.buildContext(true); OpenAPI openAPI = context.read(); if (StringUtils.isNotBlank(config.getFilterClass())) { try { OpenAPISpecFilter filterImpl = (OpenAPISpecFilter) this.getClass().getClassLoader().loadClass(config.getFilterClass()).newInstance(); SpecFilter f = new SpecFilter(); openAPI = f.filter(openAPI, filterImpl, new HashMap<>(), new HashMap<>(), new HashMap<>()); } catch (Exception e) { getLog().error("Error applying filter to API specification", e); throw new MojoExecutionException("Error applying filter to API specification: " + e.getMessage(), e); } } String openapiJson = null; String openapiYaml = null; if (Format.JSON.equals(outputFormat) || Format.JSONANDYAML.equals(outputFormat)) { if (config.isPrettyPrint() != null && config.isPrettyPrint()) { openapiJson = context.getOutputJsonMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(openAPI); } else { openapiJson = context.getOutputJsonMapper().writeValueAsString(openAPI); } } if (Format.YAML.equals(outputFormat) || Format.JSONANDYAML.equals(outputFormat)) { if (config.isPrettyPrint() != null && config.isPrettyPrint()) { openapiYaml = context.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(openAPI); } else { openapiYaml = context.getOutputYamlMapper().writeValueAsString(openAPI); } } Path path = Paths.get(outputPath, "temp"); final File parentFile = path.toFile().getParentFile(); if (parentFile != null) { parentFile.mkdirs(); } if (openapiJson != null) { path = Paths.get(outputPath, outputFileName + ".json"); Files.write(path, openapiJson.getBytes(Charset.forName(encoding))); getLog().info( "JSON output: " + path.toFile().getCanonicalPath()); } if (openapiYaml != null) { path = Paths.get(outputPath, outputFileName + ".yaml"); Files.write(path, openapiYaml.getBytes(Charset.forName(encoding))); getLog().info( "YAML output: " + path.toFile().getCanonicalPath()); } } catch (OpenApiConfigurationException e) { getLog().error( "Error resolving API specification" , e); throw new MojoFailureException(e.getMessage(), e); } catch (IOException e) { getLog().error( "Error writing API specification" , e); throw new MojoExecutionException("Failed to write API definition", e); } catch (Exception e) { getLog().error( "Error resolving API specification" , e); throw new MojoExecutionException(e.getMessage(), e); } } private void setDefaultsIfMissing(SwaggerConfiguration config) { if (prettyPrint == null) { prettyPrint = Boolean.FALSE; } if (readAllResources == null) { readAllResources = Boolean.TRUE; } if (sortOutput == null) { sortOutput = Boolean.FALSE; } if (alwaysResolveAppPath == null) { alwaysResolveAppPath = Boolean.FALSE; } if (skipResolveAppPath == null) { skipResolveAppPath = Boolean.FALSE; } if (openapi31 == null) { openapi31 = Boolean.FALSE; } if (convertToOpenAPI31 == null) { convertToOpenAPI31 = Boolean.FALSE; } if (config.isPrettyPrint() == null) { config.prettyPrint(prettyPrint); } if (config.isReadAllResources() == null) { config.readAllResources(readAllResources); } if (config.isSortOutput() == null) { config.sortOutput(sortOutput); } if (config.isAlwaysResolveAppPath() == null) { config.alwaysResolveAppPath(alwaysResolveAppPath); } if (config.isSkipResolveAppPath() == null) { config.skipResolveAppPath(skipResolveAppPath); } if (config.isOpenAPI31() == null) { config.setOpenAPI31(openapi31); } if (config.isConvertToOpenAPI31() == null) { config.setConvertToOpenAPI31(convertToOpenAPI31); } } /** * Read the content of given file as either json or yaml and maps it to given class * * @param filePath to read content from * @param outputClass to map to * @param configName for logging, what user config will be read * @param mapped type * @return empty optional if not path was given or the file was empty, read instance otherwis * @throws MojoFailureException if given path is not file, could not be read or is not proper json or yaml */ private Optional readStructuredDataFromFile(String filePath, Class outputClass, String configName) throws MojoFailureException { try { // ignore if config is not provided if (StringUtils.isBlank(filePath)) { return Optional.empty(); } Path pathObj = Paths.get(filePath); // if file does not exist or is not an actual file, finish with error if (!pathObj.toFile().exists() || !pathObj.toFile().isFile()) { throw new IllegalArgumentException( format("passed path does not exist or is not a file: '%s'", filePath)); } String fileContent = new String(Files.readAllBytes(pathObj), encoding); // if provided file is empty, log warning and finish if (StringUtils.isBlank(fileContent)) { getLog().warn(format("It seems that file '%s' defined in config %s is empty", pathObj.toString(), configName)); return Optional.empty(); } // get mappers in the order based on file extension List, T>> mappers = getSortedMappers(pathObj); T instance = null; List caughtExs = new ArrayList<>(); // iterate through mappers and see if one is able to parse for (BiFunction, T> mapper : mappers) { try { instance = mapper.apply(fileContent, outputClass); break; } catch (Exception e) { caughtExs.add(e); } } // if no mapper could read the content correctly, finish with error if (instance == null) { if (caughtExs.isEmpty()) { caughtExs.add(new IllegalStateException("undefined state")); } // we give more importance to the first exception, it was produced by the preferred mapper Throwable caughtEx = caughtExs.get(0); getLog().error(format("Could not read file '%s' for config %s", pathObj, configName), caughtEx); if(caughtExs.size() > 1){ for (Throwable ex : caughtExs.subList(1, caughtExs.size())) { getLog().warn(format("Also could not read file '%s' for config %s with alternate mapper", pathObj, configName), ex); } } throw new IllegalStateException(caughtEx.getMessage(), caughtEx); } return Optional.of(instance); } catch (Exception e) { getLog().error(format("Error reading/deserializing config %s file", configName), e); throw new MojoFailureException(e.getMessage(), e); } } /** * Get sorted list of mappers based on given filename. *

* Will sort the 2 supported mappers: json and yaml based on what file extension is used. * * @param pathObj to get extension from. * @param mapped type * @return list of mappers */ private List, T>> getSortedMappers(Path pathObj) { String ext = FileUtils.extension(pathObj.toString()); boolean yamlPreferred = false; if (ext.equalsIgnoreCase("yaml") || ext.equalsIgnoreCase("yml")) { yamlPreferred = true; } List, T>> list = new ArrayList<>(2); list.add((content, typeClass) -> { try { return Json.mapper().readValue(content, typeClass); } catch (IOException e) { throw new IllegalStateException(e); } }); list.add((content, typeClass) -> { try { return Yaml.mapper().readValue(content, typeClass); } catch (IOException e) { throw new IllegalStateException(e); } }); if (yamlPreferred) { Collections.reverse(list); } return Collections.unmodifiableList(list); } private SwaggerConfiguration mergeConfig(OpenAPI openAPIInput, SwaggerConfiguration config) { // overwrite all settings provided by other maven config if (StringUtils.isNotBlank(filterClass)) { config.filterClass(filterClass); } if (isCollectionNotBlank(ignoredRoutes)) { config.ignoredRoutes(ignoredRoutes); } if (prettyPrint != null) { config.prettyPrint(prettyPrint); } if (sortOutput != null) { config.sortOutput(sortOutput); } if (alwaysResolveAppPath != null) { config.alwaysResolveAppPath(alwaysResolveAppPath); } if (skipResolveAppPath != null) { config.skipResolveAppPath(skipResolveAppPath); } if (readAllResources != null) { config.readAllResources(readAllResources); } if (StringUtils.isNotBlank(readerClass)) { config.readerClass(readerClass); } if (StringUtils.isNotBlank(scannerClass)) { config.scannerClass(scannerClass); } if (isCollectionNotBlank(resourceClasses)) { config.resourceClasses(resourceClasses); } if (openAPIInput != null) { config.openAPI(openAPIInput); } if (isCollectionNotBlank(resourcePackages)) { config.resourcePackages(resourcePackages); } if (StringUtils.isNotBlank(objectMapperProcessorClass)) { config.objectMapperProcessorClass(objectMapperProcessorClass); } if (StringUtils.isNotBlank(defaultResponseCode)) { config.defaultResponseCode(defaultResponseCode); } if (StringUtils.isNotBlank(defaultResponseCode)) { config.defaultResponseCode(defaultResponseCode); } if (StringUtils.isNotBlank(validatorProcessorClass)) { config.validatorProcessorClass(validatorProcessorClass); } if (StringUtils.isNotBlank(groupsValidationStrategy)) { config.groupsValidationStrategy(Configuration.GroupsValidationStrategy.valueOf(groupsValidationStrategy)); } if (isCollectionNotBlank(modelConverterClasses)) { config.modelConverterClasses(modelConverterClasses); } if (openapi31 != null) { config.openAPI31(openapi31); } if (StringUtils.isNotBlank(schemaResolution)) { config.schemaResolution(Schema.SchemaResolution.valueOf(schemaResolution)); } if (StringUtils.isNotBlank(openAPIVersion)) { config.openAPIVersion(openAPIVersion); } return config; } private boolean isCollectionNotBlank(Collection collection) { return collection != null && !collection.isEmpty(); } @Parameter( property = "resolve.outputFileName", defaultValue = "openapi") private String outputFileName = "openapi"; @Parameter( property = "resolve.outputPath" ) private String outputPath; @Parameter( property = "resolve.outputFormat", defaultValue = "JSON") private Format outputFormat = Format.JSON; @Parameter( property = "resolve.resourcePackages" ) private Set resourcePackages; @Parameter( property = "resolve.resourceClasses" ) private Set resourceClasses; @Parameter( property = "resolve.modelConverterClasses" ) private LinkedHashSet modelConverterClasses; @Parameter( property = "resolve.filterClass" ) private String filterClass; @Parameter( property = "resolve.readerClass" ) private String readerClass; @Parameter( property = "resolve.scannerClass" ) private String scannerClass; /** * @since 2.0.6 */ @Parameter( property = "resolve.objectMapperProcessorClass" ) private String objectMapperProcessorClass; /** * @since 2.2.17 */ @Parameter( property = "resolve.defaultResponseCode" ) private String defaultResponseCode; /** * @since 2.2.29 */ @Parameter( property = "resolve.validatorProcessorClass" ) private String validatorProcessorClass; /** * @since 2.2.19 */ @Parameter( property = "resolve.groupsValidationStrategy" ) private String groupsValidationStrategy; @Parameter(property = "resolve.prettyPrint") private Boolean prettyPrint; @Parameter(property = "resolve.readAllResources") private Boolean readAllResources; @Parameter( property = "resolve.ignoredRoutes" ) private Collection ignoredRoutes; /** * @since 2.0.6 */ @Parameter(property = "resolve.contextId", defaultValue = "${project.artifactId}") private String contextId; @Parameter( property = "resolve.skip" ) private Boolean skip = Boolean.FALSE; @Parameter( property = "resolve.openapiFilePath") private String openapiFilePath; /** * @since 2.0.8 */ @Parameter(property = "resolve.configurationFilePath") private String configurationFilePath; @Parameter(defaultValue = "${project}", readonly = true) private MavenProject project; @Parameter( property = "resolve.encoding" ) private String encoding; /** * @since 2.1.6 */ @Parameter(property = "resolve.sortOutput") private Boolean sortOutput; /** * @since 2.1.9 */ @Parameter(property = "resolve.alwaysResolveAppPath") private Boolean alwaysResolveAppPath; /** * @since 2.1.15 */ @Parameter(property = "resolve.skipResolveAppPath") private Boolean skipResolveAppPath; /** * @since 2.2.0 */ @Parameter(property = "resolve.openapi31") private Boolean openapi31; /** * @since 2.2.12 */ @Parameter(property = "resolve.convertToOpenAPI31") private Boolean convertToOpenAPI31; /** * @since 2.2.24 */ @Parameter(property = "resolve.schemaResolution") private String schemaResolution; /** * @since 2.2.28 */ @Parameter(property = "resolve.openAPIVersion") private String openAPIVersion; private String projectEncoding = "UTF-8"; private SwaggerConfiguration config; public String getOutputPath() { return outputPath; } public String getOpenapiFilePath() { return openapiFilePath; } String getConfigurationFilePath() { return configurationFilePath; } void setContextId(String contextId) { this.contextId = contextId; } SwaggerConfiguration getInternalConfiguration() { return config; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/ASwaggerMavenIntegrationTest.java ================================================ package io.swagger.v3.plugin.maven; import io.swagger.v3.core.util.Json; import io.swagger.v3.core.util.Json31; import io.swagger.v3.core.util.Yaml; import io.swagger.v3.core.util.Yaml31; import io.swagger.v3.oas.models.OpenAPI; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.RandomStringUtils; import org.codehaus.plexus.configuration.PlexusConfiguration; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.function.Consumer; public abstract class ASwaggerMavenIntegrationTest extends BetterAbstractMojoTestCase { protected void setUp() throws Exception { // required for mojo lookups to work super.setUp(); } protected void tearDown() throws Exception { super.tearDown(); } SwaggerMojo runTest(File pom) throws Exception { return runTest(pom, this::validateOpenApiContent); } SwaggerMojo runTest(File pom, Consumer validator) throws Exception { assertNotNull(pom); assertTrue(pom.exists()); SwaggerMojo swaggerMojo = (SwaggerMojo) lookupConfiguredMojo(pom, "resolve"); // set random context id to not mix states with multiple tests swaggerMojo.setContextId(RandomStringUtils.randomAscii(32)); assertNotNull(swaggerMojo); swaggerMojo.execute(); final PlexusConfiguration config = extractPluginConfiguration("swagger-maven-plugin", pom); String outputPath = swaggerMojo.getOutputPath(); String outputFile = config.getChild("outputFileName").getValue(); if (outputFile == null) { outputFile = "openapi"; } boolean isOpenAPI31 = swaggerMojo.getInternalConfiguration() != null && Boolean.TRUE.equals(swaggerMojo.getInternalConfiguration().isOpenAPI31()); String format = config.getChild("outputFormat").getValue(); if (format.toLowerCase().equals("yaml") || format.toLowerCase().equals("jsonandyaml")) { Path path = Paths.get(outputPath, outputFile + ".yaml"); File file = path.toFile(); assertTrue(Files.isRegularFile(path)); String content = FileUtils.readFileToString(file, "UTF-8"); final OpenAPI openAPI; if (isOpenAPI31) { openAPI = Yaml31.mapper().readValue(content, OpenAPI.class); } else { openAPI = Yaml.mapper().readValue(content, OpenAPI.class); } assertNotNull(openAPI); validator.accept(openAPI); } if (format.toLowerCase().equals("json") || format.toLowerCase().equals("jsonandyaml")) { Path path = Paths.get(outputPath, outputFile + ".json"); File file = path.toFile(); assertTrue(Files.isRegularFile(path)); String content = FileUtils.readFileToString(file, "UTF-8"); final OpenAPI openAPI; if (isOpenAPI31) { openAPI = Json31.mapper().readValue(content, OpenAPI.class); } else { openAPI = Json.mapper().readValue(content, OpenAPI.class); } assertNotNull(openAPI); validator.accept(openAPI); } return swaggerMojo; } void validateOpenApiContent(OpenAPI openAPI) { assertEquals(2, openAPI.getServers().get(0).getVariables().size()); assertNotNull(openAPI.getInfo()); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/BetterAbstractMojoTestCase.java ================================================ package io.swagger.v3.plugin.maven; import org.apache.maven.DefaultMaven; import org.apache.maven.Maven; import org.apache.maven.execution.*; import org.apache.maven.plugin.Mojo; import org.apache.maven.plugin.testing.AbstractMojoTestCase; import org.apache.maven.project.MavenProject; import org.apache.maven.project.ProjectBuilder; import org.apache.maven.project.ProjectBuildingRequest; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory; import org.eclipse.aether.repository.LocalRepository; import java.io.File; import java.util.Collections; /* * Copied from https://github.com/ahgittin/license-audit-maven-plugin */ /** * Use this as you would {@link AbstractMojoTestCase}, * where you want more of the standard maven defaults to be set * (and where the {@link AbstractMojoTestCase} leaves them as null or empty). * This includes: *

  • local repo, repo sessions and managers configured *
  • maven default remote repos installed (NB: this does not use your ~/.m2 local settings) *
  • system properties are copies *

    * No changes to subclass code is needed; this simply intercepts the {@link #newMavenSession(MavenProject)} method * used by the various {@link #lookupMojo(String, File)} methods. *

    * This also provides new methods, {@link #newMavenSession()} to conveniently create a maven session, * and {@link #lookupConfiguredMojo(File, String)} so you don't have to always build the project yourself. */ public abstract class BetterAbstractMojoTestCase extends AbstractMojoTestCase { protected MavenSession newMavenSession() { try { MavenExecutionRequest request = new DefaultMavenExecutionRequest(); MavenExecutionResult result = new DefaultMavenExecutionResult(); // populate sensible defaults, including repository basedir and remote repos MavenExecutionRequestPopulator populator; populator = getContainer().lookup(MavenExecutionRequestPopulator.class); populator.populateDefaults(request); // this is needed to allow java profiles to get resolved; i.e. avoid during project builds: // [ERROR] Failed to determine Java version for profile java-1.5-detected @ org.apache.commons:commons-parent:22, /Users/alex/.m2/repository/org/apache/commons/commons-parent/22/commons-parent-22.pom, line 909, column 14 request.setSystemProperties(System.getProperties()); // and this is needed so that the repo session in the maven session // has a repo manager, and it points at the local repo // (cf MavenRepositorySystemUtils.newSession() which is what is otherwise done) DefaultMaven maven = (DefaultMaven) getContainer().lookup(Maven.class); DefaultRepositorySystemSession repoSession = (DefaultRepositorySystemSession) maven.newRepositorySession(request); repoSession.setLocalRepositoryManager( new SimpleLocalRepositoryManagerFactory().newInstance(repoSession, new LocalRepository(request.getLocalRepository().getBasedir()))); @SuppressWarnings("deprecation") MavenSession session = new MavenSession(getContainer(), repoSession, request, result); return session; } catch (Exception e) { throw new RuntimeException(e); } } /** * Extends the super to use the new {@link #newMavenSession()} introduced here * which sets the defaults one expects from maven; the standard test case leaves a lot of things blank */ @Override protected MavenSession newMavenSession(MavenProject project) { MavenSession session = newMavenSession(); session.setCurrentProject(project); session.setProjects(Collections.singletonList(project)); return session; } /** * As {@link #lookupConfiguredMojo(MavenProject, String)} but taking the pom file * and creating the {@link MavenProject}. */ protected Mojo lookupConfiguredMojo(File pom, String goal) throws Exception { assertNotNull(pom); assertTrue(pom.exists()); this.getContainer().addComponent(new IncludeProjectDependenciesComponentConfigurator(), org.codehaus.plexus.component.configurator.ComponentConfigurator.class, "include-project-dependencies"); ProjectBuildingRequest buildingRequest = newMavenSession().getProjectBuildingRequest(); ProjectBuilder projectBuilder = lookup(ProjectBuilder.class); MavenProject project = projectBuilder.build(pom, buildingRequest).getProject(); return lookupConfiguredMojo(project, goal); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/SwaggerConfigFileTest.java ================================================ package io.swagger.v3.plugin.maven; import io.swagger.v3.oas.models.media.Schema; import java.io.File; import java.math.BigDecimal; public class SwaggerConfigFileTest extends ASwaggerMavenIntegrationTest { public void testResolveFromConfigIncludingOpenApi() throws Exception { File pom = getTestFile("src/test/resources/pom.resolveToFileFromConfigAndOpenApi.xml"); SwaggerMojo mojo = runTest(pom, openAPI -> { assertEquals(1, openAPI.getServers().get(0).getVariables().size()); assertNotNull(openAPI.getInfo()); }); assertTrue(mojo.getInternalConfiguration().isPrettyPrint()); assertEquals(1, mojo.getInternalConfiguration().getResourcePackages().size()); assertEquals("io.swagger.v3.plugin.maven.petstore.petstore", mojo.getInternalConfiguration().getResourcePackages().iterator().next()); assertEquals(1, mojo.getInternalConfiguration().getOpenAPI().getServers().get(0).getVariables().size()); } public void testResolveFromConfig() throws Exception { File pom = getTestFile("src/test/resources/pom.resolveToFileFromConfig.xml"); SwaggerMojo mojo = runTest(pom); assertTrue(mojo.getInternalConfiguration().isPrettyPrint()); assertEquals(1, mojo.getInternalConfiguration().getResourcePackages().size()); assertEquals("io.swagger.v3.plugin.maven.petstore.petstore", mojo.getInternalConfiguration().getResourcePackages().iterator().next()); assertEquals(2, mojo.getInternalConfiguration().getOpenAPI().getServers().get(0).getVariables().size()); } public void testResolveFromConfigWithOpenAPI31Option() throws Exception { File pom = getTestFile("src/test/resources/pom.resolveToFileFromConfigWithOAS3.1Filter.xml"); SwaggerMojo mojo = runTest(pom, openAPI -> { assertEquals("3.1.0", openAPI.getOpenapi()); assertNotNull(openAPI.getInfo()); assertNotNull(openAPI.getComponents()); assertNotNull(openAPI.getComponents().getSchemas()); assertNotNull(openAPI.getComponents().getSchemas().get("Address")); assertNotNull(openAPI.getComponents().getSchemas().get("Address").getProperties()); Schema codeProperty = (Schema) openAPI.getComponents().getSchemas().get("Address").getProperties().get("code"); assertNotNull(codeProperty); assertNotNull(codeProperty.getMaximum()); assertEquals(new BigDecimal(50), codeProperty.getMaximum()); assertNotNull(codeProperty.getExclusiveMaximumValue()); assertEquals(new BigDecimal(50), codeProperty.getExclusiveMaximumValue()); }); assertTrue(mojo.getInternalConfiguration().isPrettyPrint()); assertTrue(mojo.getInternalConfiguration().isOpenAPI31()); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/SwaggerResolveTest.java ================================================ package io.swagger.v3.plugin.maven; import io.swagger.v3.oas.models.OpenAPI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; public class SwaggerResolveTest extends ASwaggerMavenIntegrationTest { protected static Logger LOGGER = LoggerFactory.getLogger(SwaggerResolveTest.class); public void testResolve() throws Exception { File pom = getTestFile("src/test/resources/pom.resolveToFile.xml"); checkOutput(runTest(pom)); } public void testResolve31() throws Exception { File pom = getTestFile("src/test/resources/pom.resolveToFile31.xml"); checkOutput(runTest(pom, this::validateOpenApi31Content)); } void validateOpenApi31Content(OpenAPI openAPI) { assertEquals( Boolean.TRUE, openAPI .getPaths() .get("/pet31") .getPut() .getResponses() .get("200") .getContent() .get("application/xml") .getSchema() .getReadOnly()); } public void testResolveWithFilter() throws Exception { File pom = getTestFile("src/test/resources/pom.resolveToFileWithFilter.xml"); checkOutput(runTest(pom)); } public void testResolveNoName() throws Exception { File pom = getTestFile("src/test/resources/pom.resolveToFileNoName.xml"); checkOutput(runTest(pom)); } public void testResolveJsonAndYaml() throws Exception { File pom = getTestFile("src/test/resources/pom.resolveToFileJsonAndYaml.xml"); checkOutput(runTest(pom)); } public void testResolveWithJsonInput() throws Exception { File pom = getTestFile("src/test/resources/pom.resolveToFileFromJsonInput.xml"); checkOutput(runTest(pom)); } private void checkOutput(SwaggerMojo mojo) { assertNull(mojo.getConfigurationFilePath()); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/EmptyPetResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore; /** * An Empty PetResource Class */ public class EmptyPetResource { } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/PetResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore; import io.swagger.v3.plugin.maven.resources.QueryResultBean; import io.swagger.v3.plugin.maven.resources.data.PetData; import io.swagger.v3.plugin.maven.resources.exception.NotFoundException; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; @Consumes("application/json") @Path("/pet") @Produces({"application/json", "application/xml"}) public class PetResource { static PetData petData = new PetData(); @GET @Path("/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or nonintegers will simulate API error conditions", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched"/*, _enum = "range[1,10]"*/, required = true) @PathParam("petId") final Long petId) throws NotFoundException { Pet pet = petData.getPetById(petId); if (null != pet) { return Response.ok().entity(pet).build(); } else { throw new NotFoundException(404, "Pet not found"); } } @POST @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPet( @Parameter(description = "Pet object that needs to be added to the store", required = true) final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodynoannotation") @Consumes({"application/json", "application/xml"}) @Produces({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store no annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetNoAnnotation(final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyid") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer with generic parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByInteger( @Parameter(description = "Pet object that needs to be added to the store", required = true) final int petId) { return Response.ok().entity("SUCCESS").build(); } @POST @Path("/bodyidnoannotation") @Consumes({"application/json", "application/xml"}) @Operation(summary = "Add a new pet to the store passing an integer without parameter annotation", responses = { @ApiResponse(responseCode = "405", description = "Invalid input") }) public Response addPetByIntegerNoAnnotation(final int petId) { return Response.ok().entity("SUCCESS").build(); } @PUT @Operation(summary = "Update an existing pet", responses = { @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found"), @ApiResponse(responseCode = "405", description = "Validation exception")}) public Response updatePet( @Parameter(description = "Pet object that needs to be added to the store", required = true) final Pet pet) { petData.addPet(pet); return Response.ok().entity("SUCCESS").build(); } @GET @Path("/findByStatus") @Produces("application/xml") @Operation(summary = "Finds Pets by status", description = "Multiple status values can be provided with comma seperated strings", responses = { @ApiResponse( content = @Content(mediaType = "application/json", schema = @Schema(implementation = Pet.class))), @ApiResponse( responseCode = "400", description = "Invalid status value" )} ) public Response findPetsByStatus( @Parameter(description = "Status values that need to be considered for filter", required = true) @QueryParam("status") final String status, @BeanParam final QueryResultBean qr ) { return Response.ok(petData.findPetByStatus(status)).build(); } @GET @Path("/findByTags") @Produces("application/json") @Operation(summary = "Finds Pets by tags", description = "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.", responses = { @ApiResponse(description = "Pets matching criteria", content = @Content(schema = @Schema(implementation = Pet.class)) ), @ApiResponse(description = "Invalid tag value", responseCode = "400") }) @Deprecated public Response findPetsByTags( @Parameter(description = "Tags to filter by", required = true) @QueryParam("tags") final String tags) { return Response.ok(petData.findPetByTags(tags)).build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/callback/ComplexCallbackResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.callback; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; public class ComplexCallbackResource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com"), @Callback( name = "testCallback2", operation = @Operation( operationId = "getAnSpecificReviews", summary = "get a review", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( implementation = User.class)))), callbackUrlExpression = "http://www.url2.com") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/complexcallback") public String simpleGet(@Parameter(description = "idParam", schema = @Schema(implementation = User.class)) @QueryParam("id") final String id) { return null; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/callback/MultipleCallbacksTestWithOperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class MultipleCallbacksTestWithOperationResource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com"), @Callback(name = "testCallback2", operation = @Operation(), callbackUrlExpression = "http://$request.query.url") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/multiplecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/callback/RepeatableCallbackResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class RepeatableCallbackResource { @Callback(name = "testCallback", operation = @Operation(), callbackUrlExpression = "http://$requests.query.url") @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com") @Callback(name = "testCallback2", operation = @Operation(), callbackUrlExpression = "http://$request.query.url") @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/repeatablecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/callback/SimpleCallbackWithOperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.callback; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.callbacks.Callback; import io.swagger.v3.oas.annotations.callbacks.Callbacks; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; public class SimpleCallbackWithOperationResource { @Callbacks({ @Callback( name = "testCallback1", operation = @Operation( operationId = "getAllReviews", summary = "get all the reviews", method = "get", responses = @ApiResponse( responseCode = "200", description = "successful operation", content = @Content( mediaType = "application/json", schema = @Schema( type = "integer", format = "int32")))), callbackUrlExpression = "http://www.url.com") }) @Operation( summary = "Simple get operation", operationId = "getWithNoParameters", responses = { @ApiResponse( responseCode = "200", description = "voila!") }) @GET @Path("/simplecallback") public String simpleGet() { return null; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/example/ExamplesResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.example; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.POST; import javax.ws.rs.Path; /** * Examples Resource Scenario */ public class ExamplesResource { @Path("/example") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(name = "Schema", description = "Schema", example = "Subscription example"), style = ParameterStyle.SIMPLE, example = "example", examples = { @ExampleObject(name = "subscriptionId_1", value = "12345", summary = "Subscription number 12345", externalValue = "Subscription external value 1"), @ExampleObject(name = "subscriptionId_2", value = "54321", summary = "Subscription number 54321", externalValue = "Subscription external value 2") }) }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example" ), examples = { @ExampleObject(name = "Default Response", value = "SubscriptionResponse", summary = "Subscription Response Example", externalValue = "Subscription Response value 1") } )) }) public SubscriptionResponse subscribe(@RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema( type = "string", format = "uuid", description = "the generated UUID", accessMode = Schema.AccessMode.READ_ONLY, example = "Schema example"), examples = { @ExampleObject(name = "Default Request", value = "SubscriptionRequest", summary = "Subscription Request Example", externalValue = "Subscription Request Value") })) User user) { return null; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/example/SubscriptionResponse.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.example; public class SubscriptionResponse { public String subscriptionId; } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/link/LinksResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.link; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with Links */ public class LinksResource { @Path("/links") @Operation(operationId = "getUserWithAddress", responses = { @ApiResponse(description = "test description", content = @Content(mediaType = "*/*", schema = @Schema(ref = "#/components/schemas/User")), links = { @Link( name = "address", operationId = "getAddress", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")), @Link( name = "user", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) })} ) @GET public String getUser(@QueryParam("userId")final String userId) { return null; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/openapidefintion/OpenAPIDefinitionResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.openapidefintion; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.info.Contact; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; /** * OpenAPIDefinition Example */ @OpenAPIDefinition( info = @Info( title = "Pet Resource Example", version = "2.0", description = "API Definition", termsOfService = "Terms of service", license = @License(name = "Apache 2.0", url = "http://foo.bar"), contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com") ), tags = { @Tag(name = "Tag 1", description = "desc 1", externalDocs = @ExternalDocumentation(description = "docs desc")), @Tag(name = "Tag 2", description = "desc 2", externalDocs = @ExternalDocumentation(description = "docs desc 2")), @Tag(name = "Tag 3") }, externalDocs = @ExternalDocumentation(description = "definition docs desc"), security = { @SecurityRequirement(name = "req 1", scopes = {"a", "b"}), @SecurityRequirement(name = "req 2", scopes = {"b", "c"}) } ) public class OpenAPIDefinitionResource { public void foo() { } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/AnnotatedSameNameOperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Default Operation without Annotation */ public class AnnotatedSameNameOperationResource { @Path("/sameOperationName") @GET @Operation(description = "Same Operation Name") public String getUser() { return new String(); } @Path("//sameOperationName") @DELETE @Operation(description = "Same Operation Name Duplicated") public String getUser(final String id) { return new String(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/ExternalDocumentationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import io.swagger.v3.plugin.maven.resources.exception.NotFoundException; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; /** * Resource with Operations Examples */ public class ExternalDocumentationResource { @GET @Path("/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions", operationId = "petId", externalDocs = @ExternalDocumentation(description = "External in Operation", url = "http://url.me")) @ExternalDocumentation(description = "External Annotation Documentation", url = "http://url.me") public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched", required = true) @PathParam("petId") Long petId) throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/FullyAnnotatedOperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import io.swagger.v3.plugin.maven.resources.exception.NotFoundException; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; /** * Resource with Operations Examples */ public class FullyAnnotatedOperationResource { @GET @Path("/fullyannotatedoperation/{petId}") @Operation(summary = "Find pet by ID", description = "Returns a pet when 0 < ID <= 10. ID > 10 or non integers will simulate API error conditions", operationId = "petId", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched", required = true) @PathParam("petId")final Long petId) throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/HiddenOperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Hidden Operation */ public class HiddenOperationResource { @Path("/hiddenbyflag") @GET @Operation(operationId = "Pets", description = "Pets Example", hidden = true) public Pet getPet() { return new Pet(); } @Path("/hiddenbyannotation") @GET @Operation(operationId = "Users", description = "Users Example") @Hidden public User getUser() { return new User(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/InterfaceResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; /** * Interface resource */ public interface InterfaceResource { @GET @Path("/interfaceoperation/{petId}") @Operation(summary = "Find pet by ID Operation in Parent", description = "Returns a pet in Parent" ) Response getPetById(@Parameter(description = "ID of pet that needs to be fetched", required = true) @PathParam("petId") final Long petId); } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/NotAnnotatedSameNameOperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Default Operation without Annotation */ public class NotAnnotatedSameNameOperationResource { @Path("/notannotatedoperation") @GET public String getUser() { return new String(); } @Path("/notannotatedoperationduplicated") @GET public String getUser(final String id) { return new String(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/OperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.NotFoundException; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; /** * Resource with Complete Operations Examples */ public class OperationResource implements InterfaceResource { @Override @Operation(summary = "Find pet by ID Operation in SubResource", description = "Returns a pet in SubResource" ) public Response getPetById(final Long petId) { return Response.ok().entity(new Pet()).build(); } @GET @Path("/operationsresource") @Operation(summary = "Find pet by ID", description = "combinatedfullyannotatedoperation/{petId}", operationId = "petId", responses = { @ApiResponse( description = "The pet", content = @Content( schema = @Schema(implementation = Pet.class) )), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found") }) public Response getPetById( @Parameter(description = "ID of pet that needs to be fetched", required = true) @QueryParam("petId") final Long petId, final String message) throws NotFoundException { return Response.ok().entity(new Pet()).build(); } @Path("/operationsresource") @POST public String getUser(final String id) { return new String(); } @Path("/operationsresource") @PUT @Operation(operationId = "combinated sameOperationName", description = "combinatedsameOperationName") public String getPerson() { return new String(); } @Path("/operationsresource") @HEAD @Operation(operationId = "combinatedsameOperationNameDuplicated", description = "combinatedsameOperationNameDuplicated") public String getPerson(final String id) { return new String(); } @Path("/operationsresource2") @GET public String getUser() { return new String(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/OperationWithoutAnnotationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Default Operation without Annotation */ public class OperationWithoutAnnotationResource { @Path("/operationwithouannotation") @GET public String getUser() { return new String(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/ServerOperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.servers.Server; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource With a Hidden Operation */ public class ServerOperationResource { @Path("/serversoperation") @GET @Operation(operationId = "Pets", description = "Pets Example", servers = { @Server(description = "server 2", url = "http://foo2") } ) public Pet getPet() { return new Pet(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/operation/SubResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.operation; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.core.Response; /** * SubResource */ public class SubResource implements InterfaceResource { @Override @Operation(summary = "Find pet by ID Operation in SubResource", description = "Returns a pet in SubResource" ) public Response getPetById(final Long petId) { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/ArraySchemaResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; public class ArraySchemaResource { @Path("/arrayschema") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) ), }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersResource.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersResource.SubscriptionResponse subscribe() { return null; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/ComplexParameterResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a multiple annotated. */ public class ComplexParameterResource { @Parameter(description = "Phone definied in Field") private String phone; public ComplexParameterResource(@Parameter(description = "phone Param", name = "phone") final String phone) { this.phone = phone; } @GET @Path("/complexparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam") @QueryParam("id") final String id, final String name, @QueryParam("lastName") final String lastName, @Parameter(description = "address", schema = @Schema(implementation = User.class)) @QueryParam("address") final String address) { return new User(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/ComplexParameterWithOperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a multiple annotated. */ public class ComplexParameterWithOperationResource { @Parameter(description = "Phone definied in Field") private String phone; public ComplexParameterWithOperationResource(@Parameter(description = "phone Param", name = "phone") final String phone) { this.phone = phone; } @GET @Path("/complexparameter") @Operation(operationId = "create User", parameters = { @Parameter(description = "Phone", name = "phone", in = ParameterIn.PATH) }) public User findUser(@Parameter(description = "idParam") @QueryParam("id") final String id, final String name, @QueryParam("lastName") final String lastName, @Parameter(description = "address", schema = @Schema(implementation = User.class)) @QueryParam("address") final String address) { return new User(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/MultipleNotAnnotatedParameter.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.POST; import javax.ws.rs.Path; /** * Class with a multiple not annotated parameter. */ public class MultipleNotAnnotatedParameter { @POST @Path("/multiplenoannotatedparameter") @Operation(operationId = "create User") public void createUser(final String id, final String name) { } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/OpenAPIJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs and open api annotation. */ public class OpenAPIJaxRSAnnotatedParameter { @GET @Path("/openapijaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam") @QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/OpenAPIWithContentJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs and open api annotation. */ public class OpenAPIWithContentJaxRSAnnotatedParameter { @GET @Path("/openapiwithcontentjaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam", content = @Content(schema = @Schema(description = "Id Schema Definition", required = true, name = "id"))) @QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/OpenAPIWithImplementationJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs and open api annotation. */ public class OpenAPIWithImplementationJaxRSAnnotatedParameter { @GET @Path("/openapiwithimplementationjaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@Parameter(description = "idParam", schema = @Schema(implementation = User.class)) @QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/ParametersResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Resource with some Parameters examples */ public class ParametersResource { @Path("/parameters") @POST @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", parameters = { @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(implementation = RepeatableParametersResource.SubscriptionResponse.class), style = ParameterStyle.SIMPLE), @Parameter(in = ParameterIn.QUERY, name = "formId", required = true, example = "Example"), @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)), @Parameter(in = ParameterIn.QUERY, name = "explodeTrue", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)), @Parameter(in = ParameterIn.QUERY, name = "explodeAvoiding", required = true, explode = Explode.TRUE, schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY )), @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) , schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY), content = @Content(schema = @Schema(type = "number", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY)) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) ), @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation2", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) }, responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersResource.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersResource.SubscriptionResponse subscribe(@Parameter(description = "idParam") @QueryParam("id") final String id) { return null; } static class SubscriptionResponse { public String subscriptionId; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/RepeatableParametersResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.Explode; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterStyle; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; public class RepeatableParametersResource { @Path("/repeatableparameter") @POST @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), style = ParameterStyle.SIMPLE) @Parameter(in = ParameterIn.QUERY, name = "formId", required = true, example = "Example") @Parameter(in = ParameterIn.QUERY, name = "explodeFalse", required = true, explode = Explode.FALSE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) @Parameter(in = ParameterIn.QUERY, name = "explodeTrue", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) @Parameter(in = ParameterIn.QUERY, name = "explodeAvoiding", required = true, explode = Explode.TRUE, schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY )) @Parameter(in = ParameterIn.QUERY, name = "arrayParameter", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) , schema = @Schema( type = "int", format = "id", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY), content = @Content(schema = @Schema(type = "number", description = "the generated id", accessMode = Schema.AccessMode.READ_ONLY)) ) @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation", required = true, explode = Explode.TRUE, array = @ArraySchema(maxItems = 10, minItems = 1, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class), uniqueItems = true ) ) @Parameter(in = ParameterIn.QUERY, name = "arrayParameterImplementation2", required = true, explode = Explode.TRUE, schema = @Schema(implementation = ParametersResource.SubscriptionResponse.class)) @Operation( operationId = "subscribe", description = "subscribes a client to updates relevant to the requestor's account, as " + "identified by the input token. The supplied url will be used as the delivery address for response payloads", responses = { @ApiResponse( description = "test description", content = @Content( mediaType = "*/*", schema = @Schema( implementation = ParametersResource.SubscriptionResponse.class) )) }) @Consumes({"application/json", "application/xml"}) public ParametersResource.SubscriptionResponse subscribe() { return null; } static class SubscriptionResponse { public String subscriptionId; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/SingleJaxRSAnnotatedParameter.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Class with a single parameter annotated with jaxrs. */ public class SingleJaxRSAnnotatedParameter { @GET @Path("/singlejaxrsannotatedparameter") @Operation(operationId = "create User") public User findUser(@QueryParam("id") final String id) { return new User(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/parameter/SingleNotAnnotatedParameter.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.parameter; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Class with a single not annotated parameter. */ public class SingleNotAnnotatedParameter { @GET @Path("/singlenoannotatedparameter") @Operation(operationId = "create User") public User findUser(final String id) { return new User(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/requestbody/RequestBodyMethodPriorityResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.requestbody; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with RequestBody inside Operation and another in Method */ public class RequestBodyMethodPriorityResource { @POST @Path("/requestbodymethodpriority") @Operation(summary = "Create user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "Inside Operation")) @RequestBody(description = "Created user object on Method", required = true, content = @Content( schema = @Schema(implementation = User.class))) public Response methodWithRequestBodyAndTwoParameters(final User user) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/requestbody/RequestBodyParameterPriorityResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.requestbody; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with RequestBody inside Operation and another in Method */ public class RequestBodyParameterPriorityResource { @POST @Path("/requestbodyparameterpriority") @Operation(summary = "Create user", description = "This can only be done by the logged in user.", requestBody = @RequestBody(description = "Inside Operation")) @RequestBody(description = "On method") public Response methodWithRequestBodyAndTwoParameters( @RequestBody(description = "Created user object inside Parameter", required = true, content = @Content( schema = @Schema(implementation = User.class)))final User user) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/requestbody/RequestBodyResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.requestbody; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; /** * Resource with RequestBody examples */ public class RequestBodyResource { @GET @Path("/methodWithRequestBodyWithoutContent") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyWithoutContent( @RequestBody(description = "Created user object", required = true) final User user) { return Response.ok().entity("").build(); } @GET @Path("/methodWithRequestBodyWithoutContentWithoutImplementation") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyWithoutContentWithoutImplementation( @RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema(name = "User", description = "User description", example = "User Description", required = true))) final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithRequestBodyAndTwoParameters") @Operation(summary = "Create user", description = "This can only be done by the logged in user.") public Response methodWithRequestBodyAndTwoParameters( @RequestBody(description = "Created user object", required = true, content = @Content( schema = @Schema(implementation = User.class))) final User user, @QueryParam("name") final String name, @QueryParam("code") final String code) { return Response.ok().entity("").build(); } @PUT @Path("/methodWithRequestBodyWithoutAnnotation") @Operation(summary = "Modify user", description = "Modifying user.") public Response methodWithRequestBodyWithoutAnnotation( final User user) { return Response.ok().entity("").build(); } @DELETE @Path("/methodWithoutRequestBodyAndTwoParameters") @Operation(summary = "Delete user", description = "This can only be done by the logged in user.") public Response methodWithoutRequestBodyAndTwoParameters( @QueryParam("name") final String name, @QueryParam("code") final String code) { return Response.ok().entity("").build(); } @PUT @Path("/methodWithRequestBodyWithoutAnnotationAndTwoConsumes") @Operation(summary = "Modify pet", description = "Modifying pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithRequestBodyWithoutAnnotationAndTwoConsumes( final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes") @Operation(summary = "Create pet", description = "Creating pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes( final Pet pet, final User user) { return Response.ok().entity("").build(); } @POST @Path("/methodWithTwoRequestBodyWithAnnotationAndTwoConsumes") @Operation(summary = "Create pet", description = "Creating pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithTwoRequestBodyWithAnnotationAndTwoConsumes( final @RequestBody(description = "Request Body Pet") Pet pet, @RequestBody(description = "Request Body User") final User user) { return Response.ok().entity("").build(); } @DELETE @Path("/methodWithOneSimpleRequestBody") @Operation(summary = "Delete pet", description = "Deleting pet.") @Consumes({"application/json", "application/xml"}) public Response methodWithOneSimpleRequestBody(final int id) { return Response.ok().entity("").build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/responses/ComplexResponseResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.responses; import io.swagger.v3.plugin.maven.resources.exception.NotFoundException; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource with some responses */ public class ComplexResponseResource { @GET @Path("/complexresponse") @Operation(summary = "Find pets", description = "Returns the Pets", responses = { @ApiResponse(description = "Response inside Operation", responseCode = "200", content = @Content(schema = @Schema(implementation = Pet.class))), @ApiResponse(description = "Default Pet", content = @Content(schema = @Schema(name = "Default Pet", description = "Default Pet", required = true, example = "New Pet"))) }) @ApiResponse(responseCode = "404", description = "Couldn't find pet") public Pet getPets() throws NotFoundException { return new Pet(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/responses/ImplementationResponseResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource with a Response at Method Level */ public class ImplementationResponseResource { @GET @Path("/implementationresponse") @Operation( summary = "Simple get operation", description = "Defines a simple get operation with no inputs and a complex output object", operationId = "getWithPayloadResponse", deprecated = true, responses = { @ApiResponse( responseCode = "200", description = "voila!", content = { @Content( mediaType = "application/json", schema = @Schema( implementation = ImplementationResponseResource.SampleResponseSchema.class) ), @Content( mediaType = "application/json", schema = @Schema( implementation = ImplementationResponseResource.SecondSampleResponseSchema.class) ) } ), @ApiResponse( responseCode = "400", description = "boo", content = @Content( mediaType = "*/*", schema = @Schema(implementation = ImplementationResponseResource.GenericError.class) ) ) } ) public void getResponses() { } static class SampleResponseSchema { @Schema(description = "the user id") private String id; } static class SecondSampleResponseSchema { @Schema(description = "the user id") private String id; } static class GenericError { private int code; private String message; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/responses/MethodResponseResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.responses; import io.swagger.v3.plugin.maven.resources.exception.NotFoundException; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with a Response at Method Level */ public class MethodResponseResource { @GET @Path("/responseinmethod") @Operation(summary = "Find pets", description = "Returns the Pets") @ApiResponse(responseCode = "200", description = "Status OK") public Response getPets() throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/responses/NoImplementationResponseResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.responses; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.links.Link; import io.swagger.v3.oas.annotations.links.LinkParameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; /** * Resource with a Response at Method Level */ public class NoImplementationResponseResource { @Path("/noimplementationresponseresource") @Operation(operationId = "getUser", responses = { @ApiResponse(description = "test description", responseCode = "400", links = { @Link( name = "user", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) }), @ApiResponse(description = "200 description", responseCode = "200", links = { @Link( name = "pet", operationId = "getUser", operationRef = "#/components/links/MyLink", parameters = @LinkParameter( name = "userId", expression = "$request.query.userId")) }) } ) @GET public NoImplementationResponseResource.User getUser(@QueryParam("userId") final String userId) { return null; } static class User { private String id; private String username; public String getId() { return id; } public void setId(final String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(final String username) { this.username = username; } } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/responses/NoResponseResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.responses; import io.swagger.v3.plugin.maven.resources.exception.NotFoundException; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; /** * Resource with a Response at Method Level */ public class NoResponseResource { @GET @Path("/noresponse") @Operation(summary = "Find pets", description = "Returns the Pets") public User getPets() throws NotFoundException { return new User(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/responses/OperationResponseResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.responses; import io.swagger.v3.plugin.maven.resources.exception.NotFoundException; import io.swagger.v3.plugin.maven.resources.model.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with the response in the Operation Annotation */ public class OperationResponseResource { @GET @Path("/responseinoperation") @Operation(summary = "Find Users", description = "Returns the Users", responses = {@ApiResponse(responseCode = "200", description = "Status OK")}) public Response getUsers() throws NotFoundException { return Response.ok().entity(new User()).build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/responses/PriorityResponseResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.responses; import io.swagger.v3.plugin.maven.resources.exception.NotFoundException; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with a Response at Method Level and Operation Level. */ public class PriorityResponseResource { @GET @Path("/priorityresponses") @Operation(summary = "Find pets", description = "Returns the Pets", responses = {@ApiResponse(responseCode = "200", description = "Inside Operation Response")}) @ApiResponse(responseCode = "200", description = "Inside Method Operation") public Response getPets() throws NotFoundException { return Response.ok().entity(new Pet()).build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/security/SecurityResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.security; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.security.OAuthFlow; import io.swagger.v3.oas.annotations.security.OAuthFlows; import io.swagger.v3.oas.annotations.security.OAuthScope; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityScheme; import javax.ws.rs.GET; import javax.ws.rs.PATCH; import javax.ws.rs.PUT; import javax.ws.rs.Path; @SecurityScheme(name = "myOauth2Security", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, description = "myOauthSecurity Description", flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "http://x.com", scopes = @OAuthScope( name = "write:pets", description = "modify pets in your account")) ) ) @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) @SecurityRequirement(name = "myOauth2Security", scopes = {"write:pets"} ) @Path("/security") public class SecurityResource { @GET @Operation(operationId = "Operation Id", description = "description") @SecurityRequirement(name = "security_key", scopes = {"write:pets", "read:pets"} ) public void getSecurity() { } @PATCH @Operation(operationId = "Operation Id 2", description = "description 2") @SecurityRequirement(name = "security_key2", scopes = {"write:pets", "read:pets"} ) public void getSecurity2() { } @PUT @Operation(operationId = "Operation Id 3", description = "description 3", security = @SecurityRequirement(name = "security_key3", scopes = {"write:pets", "read:pets"} )) public void setSecurity(String security) { } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/tags/CompleteTagResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; @OpenAPIDefinition(tags = { @Tag(name = "Definition First Tag"), @Tag(name = "Definition Second Tag full", description = "desc definition") }) @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Fifth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Sixth Tag") public class CompleteTagResource { @GET @Path("/completetags") @Operation(tags = {"Example Tag", "Second Tag"}) @Tag(name = "Third Tag") @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc", externalDocs = @ExternalDocumentation(description = "docs desc")) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/tags/TagClassResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.tags.Tag; /** * Class with Tag Annotations at Class level */ @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Fifth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class")) @Tag(name = "Sixth Tag") public class TagClassResource { } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/tags/TagMethodResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.tags; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.tags.Tag; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; public class TagMethodResource { @GET @Path("/tagsinmethod") @Tag(name = "Third Tag") @Tag(name = "Second Tag") @Tag(name = "Fourth Tag Full", description = "desc", externalDocs = @ExternalDocumentation(description = "docs desc")) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/tags/TagOpenAPIDefinitionResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.tags; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.tags.Tag; /** * Tag in the OpenAPIDefinition annotation */ @OpenAPIDefinition(tags = { @Tag(name = "Definition First Tag"), @Tag(name = "Definition Second Tag full", description = "desc definition") }) public class TagOpenAPIDefinitionResource { } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore/tags/TagOperationResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore.tags; import io.swagger.v3.oas.annotations.Operation; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; /** * Resource with a Tag at Operation Level */ public class TagOperationResource { @GET @Path("/tagoperation") @Operation(tags = {"Example Tag", "Second Tag"}) public Response getTags() { return Response.ok().entity("ok").build(); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/petstore/petstore31/PetResource.java ================================================ package io.swagger.v3.plugin.maven.petstore.petstore31; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.plugin.maven.resources.model.Pet; import javax.ws.rs.Consumes; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Path("/pet31") @Produces({"application/json", "application/xml"}) public class PetResource { @PUT @Operation(summary = "Update an existing pet", tags = {"pet"}, security = { @SecurityRequirement(name = "petstore_auth", scopes = {"write:pets", "read:pets"}), @SecurityRequirement(name = "mutual_tls", scopes = {}) }, responses = { @ApiResponse( responseCode = "200", description = "Successful operation", useReturnTypeSchema = true, content = { @Content( mediaType = "application/xml", schema = @Schema( accessMode = Schema.AccessMode.READ_ONLY, description = "A Pet in XML Format" ) ), @Content( mediaType = "application/json", schema = @Schema( accessMode = Schema.AccessMode.READ_ONLY, description = "A Pet in JSON Format" ) ) } ), @ApiResponse(responseCode = "400", description = "Invalid ID supplied"), @ApiResponse(responseCode = "404", description = "Pet not found"), @ApiResponse(responseCode = "405", description = "Validation exception") }) @Consumes({"application/json", "application/xml"}) public Pet updatePet( @RequestBody( description = "Pet object that needs to be updated in the store", required = true, content = { @Content( mediaType = "application/json", schema = @Schema( accessMode = Schema.AccessMode.WRITE_ONLY, description = "A Pet in JSON Format", requiredProperties = {"id"} ) ), @Content( mediaType = "application/xml", schema = @Schema( accessMode = Schema.AccessMode.WRITE_ONLY, description = "A Pet in XML Format", requiredProperties = {"id"} ) ) } ) Pet pet) { return null; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/MyFilter.java ================================================ package io.swagger.v3.plugin.maven.resources; import io.swagger.v3.core.filter.AbstractSpecFilter; import io.swagger.v3.core.model.ApiDescription; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.Map; import java.util.Optional; public class MyFilter extends AbstractSpecFilter { private static Logger LOGGER = LoggerFactory.getLogger(MyFilter.class); @Override public Optional filterOpenAPI( OpenAPI openAPI, Map> params, Map cookies, Map> headers) { openAPI.getInfo().setTitle("UPDATEDBYFILTER"); return Optional.of(openAPI); } @Override public Optional filterOperation( Operation operation, ApiDescription api, Map> params, Map cookies, Map> headers) { // some processing return Optional.of(operation); } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/QueryResultBean.java ================================================ package io.swagger.v3.plugin.maven.resources; import javax.ws.rs.QueryParam; public class QueryResultBean { @QueryParam("skip") private Integer skip; @QueryParam("limit") private Integer limit; public Integer getSkip() { return skip; } public void setSkip(Integer skip) { this.skip = skip; } public Integer getLimit() { return limit; } public void setLimit(Integer limit) { this.limit = limit; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/data/PetData.java ================================================ package io.swagger.v3.plugin.maven.resources.data; import io.swagger.v3.plugin.maven.resources.model.Category; import io.swagger.v3.plugin.maven.resources.model.Pet; import io.swagger.v3.plugin.maven.resources.model.Tag; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class PetData { static List pets = new ArrayList(); static List categories = new ArrayList(); static { categories.add(createCategory(1, "Dogs")); categories.add(createCategory(2, "Cats")); categories.add(createCategory(3, "Rabbits")); categories.add(createCategory(4, "Lions")); pets.add(createPet(1, categories.get(1), "Cat 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(2, categories.get(1), "Cat 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "available")); pets.add(createPet(3, categories.get(1), "Cat 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "pending")); pets.add(createPet(4, categories.get(0), "Dog 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(5, categories.get(0), "Dog 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "sold")); pets.add(createPet(6, categories.get(0), "Dog 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "pending")); pets.add(createPet(7, categories.get(3), "Lion 1", new String[]{ "url1", "url2"}, new String[]{"tag1", "tag2"}, "available")); pets.add(createPet(8, categories.get(3), "Lion 2", new String[]{ "url1", "url2"}, new String[]{"tag2", "tag3"}, "available")); pets.add(createPet(9, categories.get(3), "Lion 3", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "available")); pets.add(createPet(10, categories.get(2), "Rabbit 1", new String[]{ "url1", "url2"}, new String[]{"tag3", "tag4"}, "available")); } public Pet getPetById(long petId) { for (Pet pet : pets) { if (pet.getId() == petId) { return pet; } } return null; } public List findPetByStatus(String status) { String[] statues = status.split(","); List result = new ArrayList(); for (Pet pet : pets) { for (String s : statues) { if (s.equals(pet.getStatus())) { result.add(pet); } } } return result; } public List findPetByCategory(Category category) { return pets.stream().filter(pet -> category.equals(pet.getCategory())).collect(Collectors.toList()); } public List findPetByTags(String tags) { String[] tagList = tags.split(","); List result = new ArrayList(); for (Pet pet : pets) { if (null != pet.getTags()) { for (Tag tag : pet.getTags()) { for (String tagListString : tagList) { if (tagListString.equals(tag.getName())) { result.add(pet); } } } } } return result; } public void addPet(Pet pet) { if (pets.size() > 0) { for (int i = pets.size() - 1; i >= 0; i--) { if (pets.get(i).getId() == pet.getId()) { pets.remove(i); } } } pets.add(pet); } static Pet createPet(long id, Category cat, String name, String[] urls, String[] tags, String status) { Pet pet = new Pet(); pet.setId(id); pet.setCategory(cat); pet.setName(name); if (null != urls) { List urlObjs = new ArrayList(); for (String urlString : urls) { urlObjs.add(urlString); } pet.setPhotoUrls(urlObjs); } List tagObjs = new ArrayList(); int i = 0; if (null != tags) { for (String tagString : tags) { i = i + 1; Tag tag = new Tag(); tag.setId(i); tag.setName(tagString); tagObjs.add(tag); } } pet.setTags(tagObjs); pet.setStatus(status); return pet; } static Category createCategory(long id, String name) { Category category = new Category(); category.setId(id); category.setName(name); return category; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/data/UserData.java ================================================ package io.swagger.v3.plugin.maven.resources.data; import io.swagger.v3.plugin.maven.resources.model.User; import java.util.ArrayList; import java.util.List; public class UserData { static List users = new ArrayList(); static { users.add(createUser(1, "user1", "first name 1", "last name 1", "email1@test.com", "123-456-7890", 1)); users.add(createUser(2, "user2", "first name 2", "last name 2", "email2@test.com", "123-456-7890", 2)); users.add(createUser(3, "user3", "first name 3", "last name 3", "email3@test.com", "123-456-7890", 3)); users.add(createUser(4, "user4", "first name 4", "last name 4", "email4@test.com", "123-456-7890", 1)); users.add(createUser(5, "user5", "first name 5", "last name 5", "email5@test.com", "123-456-7890", 2)); users.add(createUser(6, "user6", "first name 6", "last name 6", "email6@test.com", "123-456-7890", 3)); users.add(createUser(7, "user7", "first name 7", "last name 7", "email7@test.com", "123-456-7890", 1)); users.add(createUser(8, "user8", "first name 8", "last name 8", "email8@test.com", "123-456-7890", 2)); users.add(createUser(9, "user9", "first name 9", "last name 9", "email9@test.com", "123-456-7890", 3)); users.add(createUser(10, "user10", "first name 10", "last name 10", "email10@test.com", "123-456-7890", 1)); users.add(createUser(11, "user?10", "first name ?10", "last name ?10", "email101@test.com", "123-456-7890", 1)); } public User findUserByName(String username) { for (User user : users) { if (user.getUsername().equals(username)) { return user; } } return null; } public void addUser(User user) { if (users.size() > 0) { for (int i = users.size() - 1; i >= 0; i--) { if (users.get(i).getUsername().equals(user.getUsername())) { users.remove(i); } } } users.add(user); } public boolean removeUser(String username) { if (users.size() > 0) { for (int i = users.size() - 1; i >= 0; i--) { if (users.get(i).getUsername().equals(username)) { users.remove(i); return true; } } } return false; } private static User createUser(long id, String username, String firstName, String lastName, String email, String phone, int userStatus) { User user = new User(); user.setId(id); user.setUsername(username); user.setFirstName(firstName); user.setLastName(lastName); user.setEmail(email); user.setPassword("XXXXXXXXXXX"); user.setPhone(phone); user.setUserStatus(userStatus); return user; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/exception/ApiException.java ================================================ package io.swagger.v3.plugin.maven.resources.exception; public class ApiException extends Exception { private int code; public ApiException(int code, String msg) { super(msg); this.code = code; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/exception/NotFoundException.java ================================================ package io.swagger.v3.plugin.maven.resources.exception; public class NotFoundException extends ApiException { private int code; public NotFoundException(int code, String msg) { super(code, msg); this.code = code; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/Category.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Category") public class Category { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } public Category() { } public Category(String name) { this.name = name; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/CustomGenerator.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerators; public class CustomGenerator extends ObjectIdGenerators.PropertyGenerator { private static final long serialVersionUID = 1L; protected CustomGenerator(Class scope) { super(scope); } @Override public ObjectIdGenerator forScope(Class scope) { return null; } @Override public ObjectIdGenerator newForSerialization(Object context) { return null; } @Override public IdKey key(Object key) { return null; } @Override public Object generateId(Object forPojo) { return null; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/ExtensionUser.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "User") @Schema( description = "User", extensions = { @Extension(name = "x-user", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "user-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) public class ExtensionUser { private long id; private String username; private String firstName; private String lastName; private String email; private String password; private String phone; private int userStatus; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "firstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement(name = "lastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone") public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @XmlElement(name = "userStatus") @Schema( description = "User Status", allowableValues = "1-registered,2-active,3-closed", extensions = { @Extension(name = "x-userStatus", properties = { @ExtensionProperty(name = "name", value = "Josh")}), @Extension(name = "userStatus-extensions", properties = { @ExtensionProperty(name = "lastName", value = "Hart"), @ExtensionProperty(name = "address", value = "House")}) } ) public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/JacksonBean.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonValue; public class JacksonBean { private String id; private String ignored; private StringValueBean bean; private NotFoundModel model; private NotFoundModel model2; @JsonIgnore public String getIgnored() { return ignored; } public void setIgnored(String ignored) { this.ignored = ignored; } public void setId(String id) { this.id = id; } public void setModel(NotFoundModel model) { this.model = model; } public StringValueBean getBean() { return bean; } public void setBean(StringValueBean bean) { this.bean = bean; } @JsonProperty("identity") public String getId() { return id; } @JsonUnwrapped public NotFoundModel getModel() { return model; } @JsonUnwrapped(prefix = "pre", suffix = "suf") public NotFoundModel getModel2() { return model2; } public void setModel2(NotFoundModel model2) { this.model2 = model2; } public static class StringValueBean { private final String value; @JsonCreator public StringValueBean(String value) { this.value = value; } @JsonValue public String getValue() { return value; } } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/ListOfStringsBeanParam.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import javax.ws.rs.QueryParam; import java.util.List; public class ListOfStringsBeanParam { @QueryParam(value = "listOfStrings") private List list; public List getList() { return list; } public void setList(List list) { this.list = list; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/ModelWithJsonIdentity.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.ObjectIdGenerators; public class ModelWithJsonIdentity { @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") @JsonProperty("PropertyGeneratorAsId") public SourceDefinition1 testPropertyGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") @JsonProperty("PropertyGeneratorAsProperty") public SourceDefinition1 testPropertyGeneratorAsProperty; public class SourceDefinition1 { public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "driverId") @JsonProperty("ChangedPropertyName") public SourceDefinition2 testChangedPropertyName; @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "driverId") @JsonProperty("ChangedPropertyName2") public SourceDefinition2 testChangedPropertyName2; static public class SourceDefinition2 { @JsonProperty("driverId") public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class) @JsonProperty("SourceWithoutPropertyAsId") public SourceDefinition3 testWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class) @JsonProperty("SourceWithoutPropertyAsProperty") public SourceDefinition3 testWithoutPropertyAsProperty; public class SourceDefinition3 { @JsonProperty("driverId") public String driver; public String name; @JsonProperty("@id") public String id; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "testName1") @JsonProperty("IntSequenceGeneratorAsId") public SourceDefinition4 testIntSequenceGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "testName2") @JsonProperty("IntSequenceGeneratorAsProperty") public SourceDefinition4 testIntSequenceGeneratorAsProperty; public class SourceDefinition4 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) @JsonProperty("IntSequenceWithoutPropertyAsId") public SourceDefinition5 testIntSequenceWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class) @JsonProperty("IntSequenceWithoutPropertyAsProperty") public SourceDefinition5 testIntSequenceWithoutPropertyAsProperty; public class SourceDefinition5 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "UUID1") @JsonProperty("UUIDGeneratorAsId") public SourceDefinition6 testUUIDGeneratorAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "UUID2") @JsonProperty("UUIDGeneratorAsProperty") public SourceDefinition6 testUUIDGeneratorAsProperty; public class SourceDefinition6 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class) @JsonProperty("UUIDGeneratorWithoutPropertyAsId") public SourceDefinition7 testUUIDGeneratorWithoutPropertyAsId; @JsonIdentityReference(alwaysAsId = false) @JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class) @JsonProperty("UUIDGeneratorWithoutPropertyAsProperty") public SourceDefinition7 testUUIDGeneratorWithoutPropertyAsProperty; public class SourceDefinition7 { public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = ObjectIdGenerators.None.class, property = "testGeneratorsNone") @JsonProperty("GeneratorsNone") public SourceDefinition8 testGeneratorsNone; public class SourceDefinition8 { @JsonProperty("driverId") public String driver; public String name; } @JsonIdentityReference(alwaysAsId = true) @JsonIdentityInfo(generator = CustomGenerator.class, property = "name") @JsonProperty("CustomGenerator") public SourceDefinition9 testCustomGenerator; public class SourceDefinition9 { public String driver; public String name; } @JsonIdentityInfo(generator = CustomGenerator.class, property = "name") @JsonProperty("WithoutJsonIdentityReference") public SourceDefinition10 testWithoutJsonIdentityReference; public class SourceDefinition10 { public String driver; public String name; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/ModelWithJsonIdentityCyclic.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import java.util.List; public class ModelWithJsonIdentityCyclic { public Long id; public List sourceDefinitions; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") public static class SourceDefinition { public String driver; public String name; @JsonIdentityReference(alwaysAsId=true) @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public ModelWithJsonIdentityCyclic model; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/MultipleBaseBean.java ================================================ package io.swagger.v3.plugin.maven.resources.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleBaseBean", subTypes = { MultipleSub1Bean.class, MultipleSub2Bean.class } ) public class MultipleBaseBean { public String beanType; public int a; public String b; } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/MultipleSub1Bean.java ================================================ package io.swagger.v3.plugin.maven.resources.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleSub1Bean" ) public class MultipleSub1Bean extends MultipleBaseBean { public int c; } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/MultipleSub2Bean.java ================================================ package io.swagger.v3.plugin.maven.resources.model; @io.swagger.v3.oas.annotations.media.Schema( description = "MultipleSub2Bean" ) public class MultipleSub2Bean extends MultipleBaseBean { public int d; } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/NotFoundModel.java ================================================ package io.swagger.v3.plugin.maven.resources.model; public class NotFoundModel { int code; String message; public NotFoundModel() { } public NotFoundModel(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/Pet.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.util.ArrayList; import java.util.List; @XmlRootElement(name = "Pet") public class Pet { private long id; private Category category; private String name; private List photoUrls = new ArrayList(); private List tags = new ArrayList(); private String status; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "category") public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElementWrapper(name = "photoUrls") @XmlElement(name = "photoUrl") public List getPhotoUrls() { return photoUrls; } public void setPhotoUrls(List photoUrls) { this.photoUrls = photoUrls; } @XmlElementWrapper(name = "tags") @XmlElement(name = "tag") public List getTags() { return tags; } public void setTags(List tags) { this.tags = tags; } @XmlElement(name = "status") @Schema(description = "pet status in the store", allowableValues = "available,pending,sold") public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/Tag.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Tag") public class Tag { private long id; private String name; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/java/io/swagger/v3/plugin/maven/resources/model/User.java ================================================ package io.swagger.v3.plugin.maven.resources.model; import io.swagger.v3.oas.annotations.media.Schema; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "User") public class User { private long id; private String username; private String firstName; private String lastName; private String email; private String password; private String phone; private int userStatus; @XmlElement(name = "id") public long getId() { return id; } public void setId(long id) { this.id = id; } @XmlElement(name = "firstName") public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(name = "username") public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement(name = "lastName") public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone") public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @XmlElement(name = "userStatus") @Schema(description = "User Status", allowableValues = "1-registered,2-active,3-closed") public int getUserStatus() { return userStatus; } public void setUserStatus(int userStatus) { this.userStatus = userStatus; } } ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/configurationFile.yaml ================================================ resourcePackages: - io.swagger.v3.plugin.maven.petstore.petstore prettyPrint: true cacheTTL: 0 openAPI: openapi: 3.0.1 servers: - url: http://foo description: server 1 variables: var1: description: var 1 enum: - "1" - "2" default: "1" var2: description: var 2 enum: - "1" - "2" default: "1" ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/configurationFile2.yaml ================================================ resourcePackages: - io.swagger.v3.plugin.maven.petstore.petstore prettyPrint: true openAPI31: true convertToOpenAPI31: true cacheTTL: 0 openAPI: openapi: 3.0.1 info: version: 1.0.0 title: OpenAPI 3.0 servers: - url: http://bar description: server 1 paths: {} components: schemas: Address: type: object properties: street: type: string example: 437 Lytton code: type: integer format: int32 minimum: 1 maximum: 50 exclusiveMaximum: true ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/logback-test.xml ================================================ ERROR %d [%thread]%level %logger - %msg%n ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/openapiinput.json ================================================ { "openapi": "3.0.1", "servers": [ { "url": "http://foo", "description": "server 1", "variables": { "var1": { "description": "var 1", "enum": [ "1", "2" ], "default": "1" }, "var2": { "description": "var 2", "enum": [ "1", "2" ], "default": "1" } } } ] } ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/openapiinput.yaml ================================================ openapi: 3.0.1 servers: - url: http://foo description: server 1 variables: var1: description: var 1 enum: - "1" - "2" default: "1" var2: description: var 2 enum: - "1" - "2" default: "1" ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/openapiinput2.yaml ================================================ openapi: 3.0.1 servers: - url: http://bar description: server 1 variables: var1: description: var 1 enum: - "1" - "2" default: "1" ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/pom.resolveToFile.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-maven-plugin-test jar 1.0-SNAPSHOT Test Resolve YAML io.swagger.core.v3 swagger-maven-plugin spec ${project.basedir}/../../../target/generatedtest ${project.basedir}/../../../src/test/resources/openapiinput.yaml YAML io.swagger.v3.plugin.maven.petstore.petstore TRUE io.swagger.core.v3 swagger-jaxrs2 ${project.version} javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1 ISO-8859-1 ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/pom.resolveToFile31.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-maven-plugin-test jar 1.0-SNAPSHOT Test Resolve YAML io.swagger.core.v3 swagger-maven-plugin spec ${project.basedir}/../../../target/generatedtest ${project.basedir}/../../../src/test/resources/openapiinput.yaml YAML io.swagger.v3.plugin.maven.petstore.petstore31 TRUE TRUE io.swagger.core.v3 swagger-jaxrs2 ${project.version} javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1 ISO-8859-1 ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/pom.resolveToFileFromConfig.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-maven-plugin-test jar 1.0-SNAPSHOT Test Resolve YAML io.swagger.core.v3 swagger-maven-plugin openapiconfig3 ${project.basedir}/../../../target/generatedtest ${project.basedir}/../../../src/test/resources/configurationFile.yaml JSONANDYAML io.swagger.core.v3 swagger-jaxrs2 ${project.version} javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1 ISO-8859-1 ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/pom.resolveToFileFromConfigAndOpenApi.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-maven-plugin-test jar 1.0-SNAPSHOT Test Resolve YAML io.swagger.core.v3 swagger-maven-plugin openapiconfig2 ${project.basedir}/../../../target/generatedtest ${project.basedir}/../../../src/test/resources/configurationFile.yaml ${project.basedir}/../../../src/test/resources/openapiinput2.yaml JSONANDYAML io.swagger.core.v3 swagger-jaxrs2 ${project.version} javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1 ISO-8859-1 ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/pom.resolveToFileFromConfigWithOAS3.1Filter.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-maven-plugin-test jar 1.0-SNAPSHOT Test Resolve YAML io.swagger.core.v3 swagger-maven-plugin openapiconfig2 ${project.basedir}/../../../target/generatedtest ${project.basedir}/../../../src/test/resources/configurationFile2.yaml JSONANDYAML true true io.swagger.core.v3 swagger-jaxrs2 ${project.version} javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1 ISO-8859-1 ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/pom.resolveToFileFromJsonInput.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-maven-plugin-test jar 1.0-SNAPSHOT Test Resolve YAML io.swagger.core.v3 swagger-maven-plugin openapiconfigjson ${project.basedir}/../../../target/generatedtest ${project.basedir}/../../../src/test/resources/openapiinput.json YAML io.swagger.v3.plugin.maven.petstore.petstore TRUE io.swagger.core.v3 swagger-jaxrs2 ${project.version} javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1 ISO-8859-1 ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/pom.resolveToFileJsonAndYaml.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-maven-plugin-test jar 1.0-SNAPSHOT Test Resolve YAML io.swagger.core.v3 swagger-maven-plugin openapi ${project.basedir}/../../../target/generatedtest ${project.basedir}/../../../src/test/resources/openapiinput.yaml JSONANDYAML io.swagger.v3.plugin.maven.petstore.petstore TRUE io.swagger.core.v3 swagger-jaxrs2 ${project.version} javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1 ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/pom.resolveToFileNoName.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-maven-plugin-test jar 1.0-SNAPSHOT Test Resolve YAML io.swagger.core.v3 swagger-maven-plugin ${project.basedir}/../../../target/generatedtest ${project.basedir}/../../../src/test/resources/openapiinput.yaml YAML io.swagger.v3.plugin.maven.petstore.petstore TRUE io.swagger.core.v3 swagger-jaxrs2 ${project.version} javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1 ================================================ FILE: modules/swagger-maven-plugin/src/test/resources/pom.resolveToFileWithFilter.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-maven-plugin-test jar 1.0-SNAPSHOT Test Resolve YAML io.swagger.core.v3 swagger-maven-plugin spec ${project.basedir}/../../../target/generatedtest ${project.basedir}/../../../src/test/resources/openapiinput.yaml YAML io.swagger.v3.plugin.maven.petstore.petstore TRUE io.swagger.v3.plugin.maven.resources.MyFilter io.swagger.core.v3 swagger-jaxrs2 ${project.version} javax.ws.rs javax.ws.rs-api 2.1 javax.servlet javax.servlet-api 3.1 ISO-8859-1 ================================================ FILE: modules/swagger-models/CODE_COVERAGE.md ================================================ # Code Coverage Report generation To generate the code coverage report, execute the following command: > mvn clean verify This will generate code coverage report in each of the modules. In order to view the same, open the following file in your browser. > target/site/jacoco/index.html ================================================ FILE: modules/swagger-models/pom.xml ================================================ io.swagger.core.v3 swagger-project 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-models swagger-models swagger-models src/main/java install src/test/resources biz.aQute.bnd bnd-maven-plugin org.apache.maven.plugins maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF io.swagger.v3.oas.models org.apache.maven.plugins maven-surefire-plugin ${surefire-version} -Djdk.attach.allowAttachSelf com.fasterxml.jackson.core jackson-core test com.fasterxml.jackson.core jackson-databind test org.testng testng test org.jmockit jmockit ${jmockit-version} test com.fasterxml.jackson.core jackson-annotations 0.07 0.0 1.49 2.28.2 ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/Components.java ================================================ package io.swagger.v3.oas.models; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.security.SecurityScheme; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * Components * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#components-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#components-object" */ public class Components { /** * @since 2.1.6 */ public static final String COMPONENTS_SCHEMAS_REF = "#/components/schemas/"; private Map schemas = null; private Map responses = null; private Map parameters = null; private Map examples = null; private Map requestBodies = null; private Map headers = null; private Map securitySchemes = null; private Map links = null; private Map callbacks = null; private java.util.Map extensions = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Map pathItems; /** * returns the schemas property from a Components instance. * * @return Map<String, Schema> schemas **/ public Map getSchemas() { return schemas; } public void setSchemas(Map schemas) { this.schemas = schemas; } public Components schemas(Map schemas) { this.schemas = schemas; return this; } public Components addSchemas(String key, Schema schemasItem) { if (this.schemas == null) { this.schemas = new LinkedHashMap<>(); } this.schemas.put(key, schemasItem); return this; } /** * returns the responses property from a Components instance. * * @return Map<String, ApiResponse> responses **/ public Map getResponses() { return responses; } public void setResponses(Map responses) { this.responses = responses; } public Components responses(Map responses) { this.responses = responses; return this; } public Components addResponses(String key, ApiResponse responsesItem) { if (this.responses == null) { this.responses = new LinkedHashMap<>(); } this.responses.put(key, responsesItem); return this; } /** * returns the parameters property from a Components instance. * * @return Map<String, Parameter> parameters **/ public Map getParameters() { return parameters; } public void setParameters(Map parameters) { this.parameters = parameters; } public Components parameters(Map parameters) { this.parameters = parameters; return this; } public Components addParameters(String key, Parameter parametersItem) { if (this.parameters == null) { this.parameters = new LinkedHashMap<>(); } this.parameters.put(key, parametersItem); return this; } /** * returns the examples property from a Components instance. * * @return Map<String, Example> examples **/ public Map getExamples() { return examples; } public void setExamples(Map examples) { this.examples = examples; } public Components examples(Map examples) { this.examples = examples; return this; } public Components addExamples(String key, Example examplesItem) { if (this.examples == null) { this.examples = new LinkedHashMap<>(); } this.examples.put(key, examplesItem); return this; } /** * returns the requestBodies property from a Components instance. * * @return Map<String, RequestBody> requestBodies **/ public Map getRequestBodies() { return requestBodies; } public void setRequestBodies(Map requestBodies) { this.requestBodies = requestBodies; } public Components requestBodies(Map requestBodies) { this.requestBodies = requestBodies; return this; } public Components addRequestBodies(String key, RequestBody requestBodiesItem) { if (this.requestBodies == null) { this.requestBodies = new LinkedHashMap<>(); } this.requestBodies.put(key, requestBodiesItem); return this; } /** * returns the headers property from a Components instance. * * @return Map<String, Header> headers **/ public Map getHeaders() { return headers; } public void setHeaders(Map headers) { this.headers = headers; } public Components headers(Map headers) { this.headers = headers; return this; } public Components addHeaders(String key, Header headersItem) { if (this.headers == null) { this.headers = new LinkedHashMap<>(); } this.headers.put(key, headersItem); return this; } /** * returns the securitySchemes property from a Components instance. * * @return Map<String, SecurityScheme> securitySchemes **/ public Map getSecuritySchemes() { return securitySchemes; } public void setSecuritySchemes(Map securitySchemes) { this.securitySchemes = securitySchemes; } public Components securitySchemes(Map securitySchemes) { this.securitySchemes = securitySchemes; return this; } public Components addSecuritySchemes(String key, SecurityScheme securitySchemesItem) { if (this.securitySchemes == null) { this.securitySchemes = new LinkedHashMap<>(); } this.securitySchemes.put(key, securitySchemesItem); return this; } /** * returns the links property from a Components instance. * * @return Map<String, Link> links **/ public Map getLinks() { return links; } public void setLinks(Map links) { this.links = links; } public Components links(Map links) { this.links = links; return this; } public Components addLinks(String key, Link linksItem) { if (this.links == null) { this.links = new LinkedHashMap<>(); } this.links.put(key, linksItem); return this; } /** * returns the callbacks property from a Components instance. * * @return Map<String, Callback> callbacks **/ public Map getCallbacks() { return callbacks; } public void setCallbacks(Map callbacks) { this.callbacks = callbacks; } public Components callbacks(Map callbacks) { this.callbacks = callbacks; return this; } public Components addCallbacks(String key, Callback callbacksItem) { if (this.callbacks == null) { this.callbacks = new LinkedHashMap<>(); } this.callbacks.put(key, callbacksItem); return this; } /** * returns the path items property from a Components instance. * * @since 2.2.0 (OpenAPI 3.1.0) * @return Map<String, PathItem> pathItems **/ @OpenAPI31 public Map getPathItems() { return pathItems; } @OpenAPI31 public void setPathItems(Map pathItems) { this.pathItems = pathItems; } @OpenAPI31 public Components pathItems(Map pathItems) { this.pathItems = pathItems; return this; } @OpenAPI31 public Components addPathItem(String key, PathItem pathItem) { if (this.pathItems == null) { this.pathItems = new LinkedHashMap<>(); } this.pathItems.put(key, pathItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Components components = (Components) o; return Objects.equals(this.schemas, components.schemas) && Objects.equals(this.responses, components.responses) && Objects.equals(this.parameters, components.parameters) && Objects.equals(this.examples, components.examples) && Objects.equals(this.requestBodies, components.requestBodies) && Objects.equals(this.headers, components.headers) && Objects.equals(this.securitySchemes, components.securitySchemes) && Objects.equals(this.links, components.links) && Objects.equals(this.callbacks, components.callbacks) && Objects.equals(this.extensions, components.extensions) && Objects.equals(this.pathItems, components.pathItems); } @Override public int hashCode() { return Objects.hash(schemas, responses, parameters, examples, requestBodies, headers, securitySchemes, links, callbacks, extensions, pathItems); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Components extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Components {\n"); sb.append(" schemas: ").append(toIndentedString(schemas)).append("\n"); sb.append(" responses: ").append(toIndentedString(responses)).append("\n"); sb.append(" parameters: ").append(toIndentedString(parameters)).append("\n"); sb.append(" examples: ").append(toIndentedString(examples)).append("\n"); sb.append(" requestBodies: ").append(toIndentedString(requestBodies)).append("\n"); sb.append(" headers: ").append(toIndentedString(headers)).append("\n"); sb.append(" securitySchemes: ").append(toIndentedString(securitySchemes)).append("\n"); sb.append(" links: ").append(toIndentedString(links)).append("\n"); sb.append(" callbacks: ").append(toIndentedString(callbacks)).append("\n"); sb.append(" pathItems: ").append(toIndentedString(pathItems)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/ExternalDocumentation.java ================================================ package io.swagger.v3.oas.models; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.Objects; /** * ExternalDocumentation * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#external-documentation-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#external-documentation-object" */ public class ExternalDocumentation { private String description = null; private String url = null; private java.util.Map extensions = null; /** * returns the description property from a ExternalDocumentation instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public ExternalDocumentation description(String description) { this.description = description; return this; } /** * returns the url property from a ExternalDocumentation instance. * * @return String url **/ public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public ExternalDocumentation url(String url) { this.url = url; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ExternalDocumentation externalDocumentation = (ExternalDocumentation) o; return Objects.equals(this.description, externalDocumentation.description) && Objects.equals(this.url, externalDocumentation.url) && Objects.equals(this.extensions, externalDocumentation.extensions); } @Override public int hashCode() { return Objects.hash(description, url, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public ExternalDocumentation extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ExternalDocumentation {\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" url: ").append(toIndentedString(url)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/OpenAPI.java ================================================ package io.swagger.v3.oas.models; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.oas.models.tags.Tag; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; /** * OpenAPI * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md" */ public class OpenAPI { private String openapi = "3.0.1"; private Info info = null; private ExternalDocumentation externalDocs = null; private List servers = null; private List security = null; private List tags = null; private Paths paths = null; private Components components = null; private java.util.Map extensions = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private String jsonSchemaDialect; public OpenAPI() {} public OpenAPI(SpecVersion specVersion) { this.specVersion = specVersion;} private SpecVersion specVersion = SpecVersion.V30; @JsonIgnore public SpecVersion getSpecVersion() { return this.specVersion; } public void setSpecVersion(SpecVersion specVersion) { this.specVersion = specVersion; } public OpenAPI specVersion(SpecVersion specVersion) { this.setSpecVersion(specVersion); return this; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private java.util.Map webhooks = null; /** * returns the openapi property from a OpenAPI instance. * * @return String openapi **/ public String getOpenapi() { return openapi; } public void setOpenapi(String openapi) { this.openapi = openapi; } public OpenAPI openapi(String openapi) { this.openapi = openapi; return this; } /** * returns the info property from a OpenAPI instance. * * @return Info info **/ public Info getInfo() { return info; } public void setInfo(Info info) { this.info = info; } public OpenAPI info(Info info) { this.info = info; return this; } /** * returns the externalDocs property from a OpenAPI instance. * * @return ExternalDocumentation externalDocs **/ public ExternalDocumentation getExternalDocs() { return externalDocs; } public void setExternalDocs(ExternalDocumentation externalDocs) { this.externalDocs = externalDocs; } public OpenAPI externalDocs(ExternalDocumentation externalDocs) { this.externalDocs = externalDocs; return this; } /** * Servers defined in the API * * @return List<Server> servers **/ public List getServers() { return servers; } public void setServers(List servers) { this.servers = servers; } public OpenAPI servers(List servers) { this.servers = servers; return this; } public OpenAPI addServersItem(Server serversItem) { if (this.servers == null) { this.servers = new ArrayList<>(); } this.servers.add(serversItem); return this; } /** * returns the security property from a OpenAPI instance. * * @return List<SecurityRequirement> security **/ public List getSecurity() { return security; } public void setSecurity(List security) { this.security = security; } public OpenAPI security(List security) { this.security = security; return this; } public OpenAPI addSecurityItem(SecurityRequirement securityItem) { if (this.security == null) { this.security = new ArrayList<>(); } this.security.add(securityItem); return this; } /** * returns the tags property from a OpenAPI instance. * * @return List<Tag> tags **/ public List getTags() { return tags; } public void setTags(List tags) { this.tags = tags; } public OpenAPI tags(List tags) { this.tags = tags; return this; } public OpenAPI addTagsItem(Tag tagsItem) { if (this.tags == null) { this.tags = new ArrayList<>(); } this.tags.add(tagsItem); return this; } /** * returns the paths property from a OpenAPI instance. * * @return Paths paths **/ public Paths getPaths() { return paths; } public void setPaths(Paths paths) { this.paths = paths; } public OpenAPI paths(Paths paths) { this.paths = paths; return this; } /** * returns the components property from a OpenAPI instance. * * @return Components components **/ public Components getComponents() { return components; } public void setComponents(Components components) { this.components = components; } public OpenAPI components(Components components) { this.components = components; return this; } /* * helpers */ public OpenAPI path(String name, PathItem path) { if (this.paths == null) { this.paths = new Paths(); } this.paths.addPathItem(name, path); return this; } public OpenAPI schema(String name, Schema schema) { if (components == null) { this.components = new Components(); } components.addSchemas(name, schema); return this; } public OpenAPI schemaRequirement(String name, SecurityScheme securityScheme) { if (components == null) { this.components = new Components(); } components.addSecuritySchemes(name, securityScheme); return this; } /** * returns the webhooks property from a OpenAPI instance. * * @since 2.2.0 (OpenAPI 3.1.0) * @return Map<String, PathItem> webhooks **/ @OpenAPI31 public Map getWebhooks() { return webhooks; } @OpenAPI31 public void setWebhooks(Map webhooks) { this.webhooks = webhooks; } @OpenAPI31 public OpenAPI webhooks(Map webhooks) { this.webhooks = webhooks; return this; } @OpenAPI31 public OpenAPI addWebhooks(String key, PathItem pathItem) { if (this.webhooks == null) { this.webhooks = new LinkedHashMap<>(); } this.webhooks.put(key, pathItem); return this; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public String getJsonSchemaDialect() { return jsonSchemaDialect; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setJsonSchemaDialect(String jsonSchemaDialect) { this.jsonSchemaDialect = jsonSchemaDialect; } @OpenAPI31 public OpenAPI jsonSchemaDialect(String jsonSchemaDialect) { this.jsonSchemaDialect = jsonSchemaDialect; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } OpenAPI openAPI = (OpenAPI) o; return Objects.equals(this.openapi, openAPI.openapi) && Objects.equals(this.info, openAPI.info) && Objects.equals(this.externalDocs, openAPI.externalDocs) && Objects.equals(this.servers, openAPI.servers) && Objects.equals(this.security, openAPI.security) && Objects.equals(this.tags, openAPI.tags) && Objects.equals(this.paths, openAPI.paths) && Objects.equals(this.components, openAPI.components) && Objects.equals(this.webhooks, openAPI.webhooks) && Objects.equals(this.extensions, openAPI.extensions) && Objects.equals(this.jsonSchemaDialect, openAPI.jsonSchemaDialect); } @Override public int hashCode() { return Objects.hash(openapi, info, externalDocs, servers, security, tags, paths, components, webhooks, extensions, jsonSchemaDialect); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public OpenAPI extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class OpenAPI {\n"); sb.append(" openapi: ").append(toIndentedString(openapi)).append("\n"); sb.append(" info: ").append(toIndentedString(info)).append("\n"); sb.append(" externalDocs: ").append(toIndentedString(externalDocs)).append("\n"); sb.append(" servers: ").append(toIndentedString(servers)).append("\n"); sb.append(" security: ").append(toIndentedString(security)).append("\n"); sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); sb.append(" paths: ").append(toIndentedString(paths)).append("\n"); sb.append(" components: ").append(toIndentedString(components)).append("\n"); if (specVersion == SpecVersion.V31) sb.append(" webhooks: ").append(toIndentedString(webhooks)).append("\n"); if (specVersion == SpecVersion.V31) sb.append(" jsonSchemaDialect: ").append(toIndentedString(jsonSchemaDialect)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/Operation.java ================================================ package io.swagger.v3.oas.models; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.callbacks.Callback; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.servers.Server; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; /** * Operation * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#operation-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#operation-object" */ public class Operation { private List tags = null; private String summary = null; private String description = null; private ExternalDocumentation externalDocs = null; private String operationId = null; private List parameters = null; private RequestBody requestBody = null; private ApiResponses responses = null; private Map callbacks = null; private Boolean deprecated = null; private List security = null; private List servers = null; private java.util.Map extensions = null; /** * returns the tags property from a Operation instance. * * @return List<String> tags **/ public List getTags() { return tags; } public void setTags(List tags) { this.tags = tags; } public Operation tags(List tags) { this.tags = tags; return this; } public Operation addTagsItem(String tagsItem) { if (this.tags == null) { this.tags = new ArrayList<>(); } this.tags.add(tagsItem); return this; } /** * returns the summary property from a Operation instance. * * @return String summary **/ public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } public Operation summary(String summary) { this.summary = summary; return this; } /** * returns the description property from a Operation instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Operation description(String description) { this.description = description; return this; } /** * returns the externalDocs property from a Operation instance. * * @return ExternalDocumentation externalDocs **/ public ExternalDocumentation getExternalDocs() { return externalDocs; } public void setExternalDocs(ExternalDocumentation externalDocs) { this.externalDocs = externalDocs; } public Operation externalDocs(ExternalDocumentation externalDocs) { this.externalDocs = externalDocs; return this; } /** * returns the operationId property from a Operation instance. * * @return String operationId **/ public String getOperationId() { return operationId; } public void setOperationId(String operationId) { this.operationId = operationId; } public Operation operationId(String operationId) { this.operationId = operationId; return this; } /** * returns the parameters property from a Operation instance. * * @return List<Parameter> parameters **/ public List getParameters() { return parameters; } public void setParameters(List parameters) { this.parameters = parameters; } public Operation parameters(List parameters) { this.parameters = parameters; return this; } public Operation addParametersItem(Parameter parametersItem) { if (this.parameters == null) { this.parameters = new ArrayList<>(); } this.parameters.add(parametersItem); return this; } /** * returns the requestBody property from a Operation instance. * * @return RequestBody requestBody **/ public RequestBody getRequestBody() { return requestBody; } public void setRequestBody(RequestBody requestBody) { this.requestBody = requestBody; } public Operation requestBody(RequestBody requestBody) { this.requestBody = requestBody; return this; } /** * returns the responses property from a Operation instance. * * @return ApiResponses responses **/ public ApiResponses getResponses() { return responses; } public void setResponses(ApiResponses responses) { this.responses = responses; } public Operation responses(ApiResponses responses) { this.responses = responses; return this; } /** * returns the callbacks property from a Operation instance. * * @return Callbacks callbacks **/ public Map getCallbacks() { return callbacks; } public void setCallbacks(Map callbacks) { this.callbacks = callbacks; } public Operation callbacks(Map callbacks) { this.callbacks = callbacks; return this; } public Operation addCallback(String key, Callback callback) { if (this.callbacks == null) { this.callbacks = new LinkedHashMap<>(); } this.callbacks.put(key, callback); return this; } /** * returns the deprecated property from a Operation instance. * * @return Boolean deprecated **/ public Boolean getDeprecated() { return deprecated; } public void setDeprecated(Boolean deprecated) { this.deprecated = deprecated; } public Operation deprecated(Boolean deprecated) { this.deprecated = deprecated; return this; } /** * returns the security property from a Operation instance. * * @return List<SecurityRequirement> security **/ public List getSecurity() { return security; } public void setSecurity(List security) { this.security = security; } public Operation security(List security) { this.security = security; return this; } public Operation addSecurityItem(SecurityRequirement securityItem) { if (this.security == null) { this.security = new ArrayList<>(); } this.security.add(securityItem); return this; } /** * returns the servers property from a Operation instance. * * @return List<Server> servers **/ public List getServers() { return servers; } public void setServers(List servers) { this.servers = servers; } public Operation servers(List servers) { this.servers = servers; return this; } public Operation addServersItem(Server serversItem) { if (this.servers == null) { this.servers = new ArrayList<>(); } this.servers.add(serversItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Operation operation = (Operation) o; return Objects.equals(this.tags, operation.tags) && Objects.equals(this.summary, operation.summary) && Objects.equals(this.description, operation.description) && Objects.equals(this.externalDocs, operation.externalDocs) && Objects.equals(this.operationId, operation.operationId) && Objects.equals(this.parameters, operation.parameters) && Objects.equals(this.requestBody, operation.requestBody) && Objects.equals(this.responses, operation.responses) && Objects.equals(this.callbacks, operation.callbacks) && Objects.equals(this.deprecated, operation.deprecated) && Objects.equals(this.security, operation.security) && Objects.equals(this.servers, operation.servers) && Objects.equals(this.extensions, operation.extensions); } @Override public int hashCode() { return Objects.hash(tags, summary, description, externalDocs, operationId, parameters, requestBody, responses, callbacks, deprecated, security, servers, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Operation extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Operation {\n"); sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); sb.append(" summary: ").append(toIndentedString(summary)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" externalDocs: ").append(toIndentedString(externalDocs)).append("\n"); sb.append(" operationId: ").append(toIndentedString(operationId)).append("\n"); sb.append(" parameters: ").append(toIndentedString(parameters)).append("\n"); sb.append(" requestBody: ").append(toIndentedString(requestBody)).append("\n"); sb.append(" responses: ").append(toIndentedString(responses)).append("\n"); sb.append(" callbacks: ").append(toIndentedString(callbacks)).append("\n"); sb.append(" deprecated: ").append(toIndentedString(deprecated)).append("\n"); sb.append(" security: ").append(toIndentedString(security)).append("\n"); sb.append(" servers: ").append(toIndentedString(servers)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/PathItem.java ================================================ package io.swagger.v3.oas.models; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.servers.Server; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * PathItem * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#path-item-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#path-item-object" */ public class PathItem { private String summary = null; private String description = null; private Operation get = null; private Operation put = null; private Operation post = null; private Operation delete = null; private Operation options = null; private Operation head = null; private Operation patch = null; private Operation trace = null; private List servers = null; private List parameters = null; private String $ref = null; private java.util.Map extensions = null; /** * returns the summary property from a PathItem instance. * * @return String summary **/ public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } public PathItem summary(String summary) { this.summary = summary; return this; } /** * returns the description property from a PathItem instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public PathItem description(String description) { this.description = description; return this; } /** * returns the get property from a PathItem instance. * * @return Operation get **/ public Operation getGet() { return get; } public void setGet(Operation get) { this.get = get; } public PathItem get(Operation get) { this.get = get; return this; } /** * returns the put property from a PathItem instance. * * @return Operation put **/ public Operation getPut() { return put; } public void setPut(Operation put) { this.put = put; } public PathItem put(Operation put) { this.put = put; return this; } /** * returns the post property from a PathItem instance. * * @return Operation post **/ public Operation getPost() { return post; } public void setPost(Operation post) { this.post = post; } public PathItem post(Operation post) { this.post = post; return this; } /** * returns the delete property from a PathItem instance. * * @return Operation delete **/ public Operation getDelete() { return delete; } public void setDelete(Operation delete) { this.delete = delete; } public PathItem delete(Operation delete) { this.delete = delete; return this; } /** * returns the options property from a PathItem instance. * * @return Operation options **/ public Operation getOptions() { return options; } public void setOptions(Operation options) { this.options = options; } public PathItem options(Operation options) { this.options = options; return this; } /** * returns the head property from a PathItem instance. * * @return Operation head **/ public Operation getHead() { return head; } public void setHead(Operation head) { this.head = head; } public PathItem head(Operation head) { this.head = head; return this; } /** * returns the patch property from a PathItem instance. * * @return Operation patch **/ public Operation getPatch() { return patch; } public void setPatch(Operation patch) { this.patch = patch; } public PathItem patch(Operation patch) { this.patch = patch; return this; } /** * returns the trace property from a PathItem instance. * * @return Operation trace **/ public Operation getTrace() { return trace; } public void setTrace(Operation trace) { this.trace = trace; } public PathItem trace(Operation trace) { this.trace = trace; return this; } public List readOperations() { List allOperations = new ArrayList<>(); if (this.get != null) { allOperations.add(this.get); } if (this.put != null) { allOperations.add(this.put); } if (this.head != null) { allOperations.add(this.head); } if (this.post != null) { allOperations.add(this.post); } if (this.delete != null) { allOperations.add(this.delete); } if (this.patch != null) { allOperations.add(this.patch); } if (this.options != null) { allOperations.add(this.options); } if (this.trace != null) { allOperations.add(this.trace); } return allOperations; } public void operation(HttpMethod method, Operation operation) { switch (method) { case PATCH: this.patch = operation; break; case POST: this.post = operation; break; case PUT: this.put = operation; break; case GET: this.get = operation; break; case OPTIONS: this.options = operation; break; case TRACE: this.trace = operation; break; case HEAD: this.head = operation; break; case DELETE: this.delete = operation; break; default: } } public enum HttpMethod { POST, GET, PUT, PATCH, DELETE, HEAD, OPTIONS, TRACE } public Map readOperationsMap() { Map result = new LinkedHashMap<>(); if (this.get != null) { result.put(HttpMethod.GET, this.get); } if (this.put != null) { result.put(HttpMethod.PUT, this.put); } if (this.post != null) { result.put(HttpMethod.POST, this.post); } if (this.delete != null) { result.put(HttpMethod.DELETE, this.delete); } if (this.patch != null) { result.put(HttpMethod.PATCH, this.patch); } if (this.head != null) { result.put(HttpMethod.HEAD, this.head); } if (this.options != null) { result.put(HttpMethod.OPTIONS, this.options); } if (this.trace != null) { result.put(HttpMethod.TRACE, this.trace); } return result; } /** * returns the servers property from a PathItem instance. * * @return List<Server> servers **/ public List getServers() { return servers; } public void setServers(List servers) { this.servers = servers; } public PathItem servers(List servers) { this.servers = servers; return this; } public PathItem addServersItem(Server serversItem) { if (this.servers == null) { this.servers = new ArrayList<>(); } this.servers.add(serversItem); return this; } /** * returns the parameters property from a PathItem instance. * * @return List<Parameter> parameters **/ public List getParameters() { return parameters; } public void setParameters(List parameters) { this.parameters = parameters; } public PathItem parameters(List parameters) { this.parameters = parameters; return this; } public PathItem addParametersItem(Parameter parametersItem) { if (this.parameters == null) { this.parameters = new ArrayList<>(); } this.parameters.add(parametersItem); return this; } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public PathItem extensions(java.util.Map extensions) { this.extensions = extensions; return this; } /** * returns the ref property from a PathItem instance. * * @return String ref **/ public String get$ref() { return $ref; } public void set$ref(String $ref) { this.$ref = $ref; } public PathItem $ref(String $ref) { set$ref($ref); return this; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof PathItem)) { return false; } PathItem pathItem = (PathItem) o; if (summary != null ? !summary.equals(pathItem.summary) : pathItem.summary != null) { return false; } if (description != null ? !description.equals(pathItem.description) : pathItem.description != null) { return false; } if (get != null ? !get.equals(pathItem.get) : pathItem.get != null) { return false; } if (put != null ? !put.equals(pathItem.put) : pathItem.put != null) { return false; } if (post != null ? !post.equals(pathItem.post) : pathItem.post != null) { return false; } if (delete != null ? !delete.equals(pathItem.delete) : pathItem.delete != null) { return false; } if (options != null ? !options.equals(pathItem.options) : pathItem.options != null) { return false; } if (head != null ? !head.equals(pathItem.head) : pathItem.head != null) { return false; } if (patch != null ? !patch.equals(pathItem.patch) : pathItem.patch != null) { return false; } if (trace != null ? !trace.equals(pathItem.trace) : pathItem.trace != null) { return false; } if (servers != null ? !servers.equals(pathItem.servers) : pathItem.servers != null) { return false; } if (parameters != null ? !parameters.equals(pathItem.parameters) : pathItem.parameters != null) { return false; } if ($ref != null ? !$ref.equals(pathItem.$ref) : pathItem.$ref != null) { return false; } return extensions != null ? extensions.equals(pathItem.extensions) : pathItem.extensions == null; } @Override public int hashCode() { int result = summary != null ? summary.hashCode() : 0; result = 31 * result + (description != null ? description.hashCode() : 0); result = 31 * result + (get != null ? get.hashCode() : 0); result = 31 * result + (put != null ? put.hashCode() : 0); result = 31 * result + (post != null ? post.hashCode() : 0); result = 31 * result + (delete != null ? delete.hashCode() : 0); result = 31 * result + (options != null ? options.hashCode() : 0); result = 31 * result + (head != null ? head.hashCode() : 0); result = 31 * result + (patch != null ? patch.hashCode() : 0); result = 31 * result + (trace != null ? trace.hashCode() : 0); result = 31 * result + (servers != null ? servers.hashCode() : 0); result = 31 * result + (parameters != null ? parameters.hashCode() : 0); result = 31 * result + ($ref != null ? $ref.hashCode() : 0); result = 31 * result + (extensions != null ? extensions.hashCode() : 0); return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class PathItem {\n"); sb.append(" summary: ").append(toIndentedString(summary)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" get: ").append(toIndentedString(get)).append("\n"); sb.append(" put: ").append(toIndentedString(put)).append("\n"); sb.append(" post: ").append(toIndentedString(post)).append("\n"); sb.append(" delete: ").append(toIndentedString(delete)).append("\n"); sb.append(" options: ").append(toIndentedString(options)).append("\n"); sb.append(" head: ").append(toIndentedString(head)).append("\n"); sb.append(" patch: ").append(toIndentedString(patch)).append("\n"); sb.append(" trace: ").append(toIndentedString(trace)).append("\n"); sb.append(" servers: ").append(toIndentedString(servers)).append("\n"); sb.append(" parameters: ").append(toIndentedString(parameters)).append("\n"); sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/Paths.java ================================================ package io.swagger.v3.oas.models; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.LinkedHashMap; import java.util.Objects; /** * Paths * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#paths-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#paths-object" */ public class Paths extends LinkedHashMap { public Paths() { } private java.util.Map extensions = null; public Paths addPathItem(String name, PathItem item) { this.put(name, item); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Paths paths = (Paths) o; return Objects.equals(this.extensions, paths.extensions) && super.equals(o); } @Override public int hashCode() { return Objects.hash(extensions, super.hashCode()); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Paths extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Paths {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/SpecVersion.java ================================================ package io.swagger.v3.oas.models; public enum SpecVersion { V30, V31 } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/annotations/OpenAPI30.java ================================================ package io.swagger.v3.oas.models.annotations; import java.lang.annotation.Inherited; @Inherited public @interface OpenAPI30 { } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/annotations/OpenAPI31.java ================================================ package io.swagger.v3.oas.models.annotations; import java.lang.annotation.Inherited; @Inherited public @interface OpenAPI31 { } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/callbacks/Callback.java ================================================ package io.swagger.v3.oas.models.callbacks; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.PathItem; import java.util.LinkedHashMap; import java.util.Objects; /** * Callback * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#callback-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#callback-object" */ public class Callback extends LinkedHashMap { public Callback() { } private java.util.Map extensions = null; private String $ref = null; /** * @since 2.0.3 */ public String get$ref() { return $ref; } /** * @since 2.0.3 */ public void set$ref(String $ref) { if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { $ref = "#/components/callbacks/" + $ref; } this.$ref = $ref; } /** * @since 2.0.3 */ public Callback $ref(String $ref) { set$ref($ref); return this; } public Callback addPathItem(String name, PathItem item) { this.put(name, item); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Callback callback = (Callback) o; if ($ref != null ? !$ref.equals(callback.$ref) : callback.$ref != null) { return false; } return Objects.equals(this.extensions, callback.extensions) && super.equals(o); } @Override public int hashCode() { return Objects.hash(extensions, $ref, super.hashCode()); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Callback extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Callback {\n"); sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/examples/Example.java ================================================ package io.swagger.v3.oas.models.examples; import io.swagger.v3.oas.models.annotations.OpenAPI31; /** * Example * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#example-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#example-object" */ public class Example { private String summary = null; private String description = null; private Object value = null; private String externalValue = null; private String $ref = null; private java.util.Map extensions = null; private boolean valueSetFlag; /** * returns the summary property from a Example instance. * * @return String summary **/ public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } public Example summary(String summary) { this.summary = summary; return this; } /** * returns the description property from a Example instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Example description(String description) { this.description = description; return this; } /** * returns the value property from a Example instance. * * @return Object value **/ public Object getValue() { return value; } public void setValue(Object value) { this.value = value; valueSetFlag = true; } public Example value(Object value) { setValue(value); return this; } /** * returns the externalValue property from a Example instance. * * @return String externalValue **/ public String getExternalValue() { return externalValue; } public void setExternalValue(String externalValue) { this.externalValue = externalValue; } public Example externalValue(String externalValue) { this.externalValue = externalValue; return this; } public String get$ref() { return $ref; } public void set$ref(String $ref) { if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { $ref = "#/components/examples/" + $ref; } this.$ref = $ref; } public Example $ref(String $ref) { set$ref($ref); return this; } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Example extensions(java.util.Map extensions) { this.extensions = extensions; return this; } public boolean getValueSetFlag() { return valueSetFlag; } public void setValueSetFlag(boolean valueSetFlag) { this.valueSetFlag = valueSetFlag; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof Example)) { return false; } Example example = (Example) o; if (summary != null ? !summary.equals(example.summary) : example.summary != null) { return false; } if (description != null ? !description.equals(example.description) : example.description != null) { return false; } if (value != null ? !value.equals(example.value) : example.value != null) { return false; } if (externalValue != null ? !externalValue.equals(example.externalValue) : example.externalValue != null) { return false; } if ($ref != null ? !$ref.equals(example.$ref) : example.$ref != null) { return false; } return extensions != null ? extensions.equals(example.extensions) : example.extensions == null; } @Override public int hashCode() { int result = summary != null ? summary.hashCode() : 0; result = 31 * result + (description != null ? description.hashCode() : 0); result = 31 * result + (value != null ? value.hashCode() : 0); result = 31 * result + (externalValue != null ? externalValue.hashCode() : 0); result = 31 * result + ($ref != null ? $ref.hashCode() : 0); result = 31 * result + (extensions != null ? extensions.hashCode() : 0); return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Example {\n"); sb.append(" summary: ").append(toIndentedString(summary)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" value: ").append(toIndentedString(value)).append("\n"); sb.append(" externalValue: ").append(toIndentedString(externalValue)).append("\n"); sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/headers/Header.java ================================================ package io.swagger.v3.oas.models.headers; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.Schema; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * Header * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#header-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#header-object" */ public class Header { private String description = null; private String $ref = null; private Boolean required = null; private Boolean deprecated = null; /** * Gets or Sets style */ public enum StyleEnum { SIMPLE("simple"); private String value; StyleEnum(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } private StyleEnum style = null; private Boolean explode = null; private Schema schema = null; private Map examples = null; private Object example = null; private Content content = null; private java.util.Map extensions = null; /** * returns the description property from a Header instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Header description(String description) { this.description = description; return this; } /** * returns the required property from a Header instance. * * @return Boolean required **/ public Boolean getRequired() { return required; } public void setRequired(Boolean required) { this.required = required; } public Header required(Boolean required) { this.required = required; return this; } /** * returns the deprecated property from a Header instance. * * @return Boolean deprecated **/ public Boolean getDeprecated() { return deprecated; } public void setDeprecated(Boolean deprecated) { this.deprecated = deprecated; } public Header deprecated(Boolean deprecated) { this.deprecated = deprecated; return this; } /** * returns the style property from a Header instance. * * @return StyleEnum style **/ public StyleEnum getStyle() { return style; } public void setStyle(StyleEnum style) { this.style = style; } public Header style(StyleEnum style) { this.style = style; return this; } /** * returns the explode property from a Header instance. * * @return Boolean explode **/ public Boolean getExplode() { return explode; } public void setExplode(Boolean explode) { this.explode = explode; } public Header explode(Boolean explode) { this.explode = explode; return this; } /** * returns the schema property from a Header instance. * * @return Schema schema **/ public Schema getSchema() { return schema; } public void setSchema(Schema schema) { this.schema = schema; } public Header schema(Schema schema) { this.schema = schema; return this; } /** * returns the examples property from a Header instance. * * @return Map<String, Example> examples **/ public Map getExamples() { return examples; } public void setExamples(Map examples) { this.examples = examples; } public Header examples(Map examples) { this.examples = examples; return this; } public Header addExample(String key, Example examplesItem) { if (this.examples == null) { this.examples = new LinkedHashMap<>(); } this.examples.put(key, examplesItem); return this; } /** * returns the example property from a Header instance. * * @return String example **/ public Object getExample() { return example; } public void setExample(Object example) { this.example = example; } public Header example(Object example) { this.example = example; return this; } /** * returns the content property from a Header instance. * * @return Content content **/ public Content getContent() { return content; } public void setContent(Content content) { this.content = content; } public Header content(Content content) { this.content = content; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Header header = (Header) o; return Objects.equals(this.description, header.description) && Objects.equals(this.required, header.required) && Objects.equals(this.deprecated, header.deprecated) && Objects.equals(this.style, header.style) && Objects.equals(this.explode, header.explode) && Objects.equals(this.schema, header.schema) && Objects.equals(this.examples, header.examples) && Objects.equals(this.example, header.example) && Objects.equals(this.content, header.content) && Objects.equals(this.extensions, header.extensions) && Objects.equals(this.$ref, header.$ref); } @Override public int hashCode() { return Objects.hash(description, required, deprecated, style, explode, schema, examples, example, content, extensions, $ref); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Header extensions(java.util.Map extensions) { this.extensions = extensions; return this; } public String get$ref() { return $ref; } public void set$ref(String $ref) { if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { $ref = "#/components/headers/" + $ref; } this.$ref = $ref; } public Header $ref(String $ref) { set$ref($ref); return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Header {\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" required: ").append(toIndentedString(required)).append("\n"); sb.append(" deprecated: ").append(toIndentedString(deprecated)).append("\n"); sb.append(" style: ").append(toIndentedString(style)).append("\n"); sb.append(" explode: ").append(toIndentedString(explode)).append("\n"); sb.append(" schema: ").append(toIndentedString(schema)).append("\n"); sb.append(" examples: ").append(toIndentedString(examples)).append("\n"); sb.append(" example: ").append(toIndentedString(example)).append("\n"); sb.append(" content: ").append(toIndentedString(content)).append("\n"); sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/info/Contact.java ================================================ package io.swagger.v3.oas.models.info; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.Objects; /** * Contact * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#contact-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#contact-object" */ public class Contact { private String name = null; private String url = null; private String email = null; private java.util.Map extensions = null; /** * returns the name property from a Contact instance. * * @return String name **/ public String getName() { return name; } public void setName(String name) { this.name = name; } public Contact name(String name) { this.name = name; return this; } /** * returns the url property from a Contact instance. * * @return String url **/ public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Contact url(String url) { this.url = url; return this; } /** * returns the email property from a Contact instance. * * @return String email **/ public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Contact email(String email) { this.email = email; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Contact contact = (Contact) o; return Objects.equals(this.name, contact.name) && Objects.equals(this.url, contact.url) && Objects.equals(this.email, contact.email) && Objects.equals(this.extensions, contact.extensions); } @Override public int hashCode() { return Objects.hash(name, url, email, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Contact extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Contact {\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" url: ").append(toIndentedString(url)).append("\n"); sb.append(" email: ").append(toIndentedString(email)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/info/Info.java ================================================ package io.swagger.v3.oas.models.info; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.Objects; /** * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#info-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#info-object" */ public class Info { private String title = null; private String description = null; private String termsOfService = null; private Contact contact = null; private License license = null; private String version = null; private java.util.Map extensions = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private String summary = null; /** * returns the title property from a Info instance. * * @return String title **/ public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Info title(String title) { this.title = title; return this; } /** * returns the description property from a Info instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Info description(String description) { this.description = description; return this; } /** * returns the termsOfService property from a Info instance. * * @return String termsOfService **/ public String getTermsOfService() { return termsOfService; } public void setTermsOfService(String termsOfService) { this.termsOfService = termsOfService; } public Info termsOfService(String termsOfService) { this.termsOfService = termsOfService; return this; } /** * returns the contact property from a Info instance. * * @return Contact contact **/ public Contact getContact() { return contact; } public void setContact(Contact contact) { this.contact = contact; } public Info contact(Contact contact) { this.contact = contact; return this; } /** * returns the license property from a Info instance. * * @return License license **/ public License getLicense() { return license; } public void setLicense(License license) { this.license = license; } public Info license(License license) { this.license = license; return this; } /** * returns the version property from a Info instance. * * @return String version **/ public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public Info version(String version) { this.version = version; return this; } /** * returns the summary property from a Info instance. * * @since 2.2.0 (OpenAPI 3.1.0) * @return String **/ @OpenAPI31 public String getSummary() { return summary; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setSummary(String summary) { this.summary = summary; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Info summary(String summary) { this.summary = summary; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Info info = (Info) o; return Objects.equals(this.title, info.title) && Objects.equals(this.description, info.description) && Objects.equals(this.termsOfService, info.termsOfService) && Objects.equals(this.contact, info.contact) && Objects.equals(this.license, info.license) && Objects.equals(this.version, info.version) && Objects.equals(this.extensions, info.extensions) && Objects.equals(this.summary, info.summary); } @Override public int hashCode() { return Objects.hash(title, description, termsOfService, contact, license, version, extensions, summary); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Info extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Info {\n"); sb.append(" title: ").append(toIndentedString(title)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" summary: ").append(toIndentedString(summary)).append("\n"); sb.append(" termsOfService: ").append(toIndentedString(termsOfService)).append("\n"); sb.append(" contact: ").append(toIndentedString(contact)).append("\n"); sb.append(" license: ").append(toIndentedString(license)).append("\n"); sb.append(" version: ").append(toIndentedString(version)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/info/License.java ================================================ package io.swagger.v3.oas.models.info; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.Objects; /** * License * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#license-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#license-object" */ public class License { private String name = null; private String url = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private String identifier = null; private java.util.Map extensions = null; /** * returns the name property from a License instance. * * @return String name **/ public String getName() { return name; } public void setName(String name) { this.name = name; } public License name(String name) { this.name = name; return this; } /** * returns the url property from a License instance. * * @return String url **/ public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public License url(String url) { this.url = url; return this; } /** * returns the identifier property from a License instance. * * @since 2.2.0 (OpenAPI 3.1.0) * @return String identifier **/ @OpenAPI31 public String getIdentifier() { return identifier; } @OpenAPI31 public void setIdentifier(String identifier) { this.identifier = identifier; } @OpenAPI31 public License identifier(String identifier) { this.identifier = identifier; return this; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } License license = (License) o; return Objects.equals(this.name, license.name) && Objects.equals(this.url, license.url) && Objects.equals(this.identifier, license.identifier) && Objects.equals(this.extensions, license.extensions); } @Override public int hashCode() { return Objects.hash(name, url, identifier, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public License extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class License {\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" url: ").append(toIndentedString(url)).append("\n"); sb.append(" identifier: ").append(toIndentedString(identifier)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/links/Link.java ================================================ package io.swagger.v3.oas.models.links; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.servers.Server; import java.util.LinkedHashMap; import java.util.Map; /** * Link * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#link-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#link-object" */ public class Link { private String operationRef = null; private String operationId = null; private Map parameters = null; private Object requestBody = null; /** * @deprecated as it's not part of OpenAPI specification */ @Deprecated private Map headers = null; private String description = null; private String $ref = null; private java.util.Map extensions = null; private Server server; /** * returns the server property from a Link instance. * * @return Server server **/ public Server getServer() { return server; } public void setServer(Server server) { this.server = server; } public Link server(Server server) { this.setServer(server); return this; } /** * returns the operationRef property from a Link instance. * * @return String operationRef **/ public String getOperationRef() { return operationRef; } public void setOperationRef(String operationRef) { this.operationRef = operationRef; } public Link operationRef(String operationRef) { this.operationRef = operationRef; return this; } /** * returns the requestBody property from a Link instance. * * @return Object requestBody **/ public Object getRequestBody() { return requestBody; } public void setRequestBody(Object requestBody) { this.requestBody = requestBody; } public Link requestBody(Object requestBody) { this.requestBody = requestBody; return this; } public String getOperationId() { return operationId; } public void setOperationId(String operationId) { this.operationId = operationId; } public Link operationId(String operationId) { this.operationId = operationId; return this; } /** * returns the parameters property from a Link instance. * * @return LinkParameters parameters **/ public Map getParameters() { return parameters; } public void setParameters(Map parameters) { this.parameters = parameters; } @Deprecated public Link parameters(String name, String parameter) { return this.addParameter(name, parameter); } public Link addParameter(String name, String parameter) { if (this.parameters == null) { this.parameters = new LinkedHashMap<>(); } this.parameters.put(name, parameter); return this; } /** * @deprecated as it's not part of OpenAPI specification */ @Deprecated public Map getHeaders() { return headers; } /** * @deprecated as it's not part of OpenAPI specification */ @Deprecated public void setHeaders(Map headers) { this.headers = headers; } /** * @deprecated as it's not part of OpenAPI specification */ @Deprecated public Link headers(Map headers) { this.headers = headers; return this; } /** * @deprecated as it's not part of OpenAPI specification */ @Deprecated public Link addHeaderObject(String name, Header header) { if (this.headers == null) { headers = new LinkedHashMap<>(); } headers.put(name, header); return this; } /** * returns the description property from a Link instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Link description(String description) { this.description = description; return this; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof Link)) { return false; } Link link = (Link) o; if (operationRef != null ? !operationRef.equals(link.operationRef) : link.operationRef != null) { return false; } if (operationId != null ? !operationId.equals(link.operationId) : link.operationId != null) { return false; } if (parameters != null ? !parameters.equals(link.parameters) : link.parameters != null) { return false; } if (requestBody != null ? !requestBody.equals(link.requestBody) : link.requestBody != null) { return false; } if (headers != null ? !headers.equals(link.headers) : link.headers != null) { return false; } if (description != null ? !description.equals(link.description) : link.description != null) { return false; } if ($ref != null ? !$ref.equals(link.$ref) : link.$ref != null) { return false; } if (extensions != null ? !extensions.equals(link.extensions) : link.extensions != null) { return false; } return server != null ? server.equals(link.server) : link.server == null; } @Override public int hashCode() { int result = operationRef != null ? operationRef.hashCode() : 0; result = 31 * result + (operationId != null ? operationId.hashCode() : 0); result = 31 * result + (parameters != null ? parameters.hashCode() : 0); result = 31 * result + (requestBody != null ? requestBody.hashCode() : 0); result = 31 * result + (headers != null ? headers.hashCode() : 0); result = 31 * result + (description != null ? description.hashCode() : 0); result = 31 * result + ($ref != null ? $ref.hashCode() : 0); result = 31 * result + (extensions != null ? extensions.hashCode() : 0); result = 31 * result + (server != null ? server.hashCode() : 0); return result; } public String get$ref() { return $ref; } public void set$ref(String $ref) { if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { $ref = "#/components/links/" + $ref; } this.$ref = $ref; } public Link $ref(String $ref) { set$ref($ref); return this; } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Link extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Link {\n"); sb.append(" operationRef: ").append(toIndentedString(operationRef)).append("\n"); sb.append(" operationId: ").append(toIndentedString(operationId)).append("\n"); sb.append(" parameters: ").append(toIndentedString(parameters)).append("\n"); sb.append(" requestBody: ").append(toIndentedString(requestBody)).append("\n"); sb.append(" headers: ").append(toIndentedString(headers)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/links/LinkParameter.java ================================================ package io.swagger.v3.oas.models.links; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.Objects; /** * LinkParameter * */ public class LinkParameter { private String value; public LinkParameter() { } private java.util.Map extensions = null; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public LinkParameter value(String value) { this.value = value; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } LinkParameter linkParameters = (LinkParameter) o; return Objects.equals(this.value, linkParameters.value) && Objects.equals(this.extensions, linkParameters.extensions); } @Override public int hashCode() { return Objects.hash(value, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public LinkParameter extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class LinkParameter {\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/ArbitrarySchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.Objects; /** * ArbitrarySchema */ public class ArbitrarySchema extends Schema { public ArbitrarySchema() { } @Override public ArbitrarySchema type(String type) { super.setType(type); return this; } @Override public ArbitrarySchema example(Object example) { if (example != null) { super.setExample(example.toString()); } else { super.setExample(example); } return this; } @Override protected Object cast(Object value) { return value; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ArbitrarySchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/ArraySchema.java ================================================ package io.swagger.v3.oas.models.media; /** * ArraySchema */ public class ArraySchema extends Schema { public ArraySchema() { super("array", null); } @Override public ArraySchema type(String type) { super.setType(type); return this; } @Override public ArraySchema items(Schema items) { super.setItems(items); return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ArraySchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/BinarySchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.Base64; import java.util.List; import java.util.Objects; /** * BinarySchema */ public class BinarySchema extends Schema { public BinarySchema() { super("string", "binary"); } @Override public BinarySchema type(String type) { super.setType(type); return this; } @Override public BinarySchema format(String format) { super.setFormat(format); return this; } public BinarySchema _default(byte[] _default) { super.setDefault(_default); return this; } @Override protected byte[] cast(Object value) { if (value != null) { try { if (value instanceof byte[]) { return (byte[]) value; } else if (value instanceof String) { if ( (System.getProperty(BINARY_STRING_CONVERSION_PROPERTY) != null && System.getProperty(BINARY_STRING_CONVERSION_PROPERTY).equals(BynaryStringConversion.BINARY_STRING_CONVERSION_BASE64.toString())) || (System.getenv(BINARY_STRING_CONVERSION_PROPERTY) != null && System.getenv(BINARY_STRING_CONVERSION_PROPERTY).equals(BynaryStringConversion.BINARY_STRING_CONVERSION_BASE64.toString()))) { return Base64.getDecoder().decode((String) value); } return value.toString().getBytes(); } else { return value.toString().getBytes(); } } catch (Exception e) { } } return null; } public BinarySchema _enum(List _enum) { super.setEnum(_enum); return this; } public BinarySchema addEnumItem(byte[] _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(_default, _enum, super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class BinarySchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/BooleanSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Set; /** * BooleanSchema */ public class BooleanSchema extends Schema { public BooleanSchema() { super("boolean", null); } @Override public BooleanSchema type(String type) { super.setType(type); return this; } @Override public BooleanSchema types(Set types) { super.setTypes(types); return this; } public BooleanSchema _default(Boolean _default) { super.setDefault(_default); return this; } @Override protected Boolean cast(Object value) { if (value != null) { try { return Boolean.parseBoolean(value.toString()); } catch (Exception e) { } } return null; } public BooleanSchema _enum(List _enum) { this._enum = _enum; return this; } public BooleanSchema addEnumItem(Boolean _enumItem) { if (this._enum == null) { this._enum = new ArrayList(); } this._enum.add(_enumItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class BooleanSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/ByteArraySchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.Base64; import java.util.List; import java.util.Objects; /** * ByteArraySchema */ public class ByteArraySchema extends Schema { public ByteArraySchema() { super("string", "byte"); } @Override public ByteArraySchema type(String type) { super.setType(type); return this; } @Override public ByteArraySchema format(String format) { super.setFormat(format); return this; } public ByteArraySchema _default(byte[] _default) { super.setDefault(_default); return this; } @Override protected byte[] cast(Object value) { if (value != null) { try { if (value instanceof byte[]) { return (byte[]) value; } else if (value instanceof String) { if ( (System.getProperty(BINARY_STRING_CONVERSION_PROPERTY) != null && System.getProperty(BINARY_STRING_CONVERSION_PROPERTY).equals(BynaryStringConversion.BINARY_STRING_CONVERSION_BASE64.toString())) || (System.getenv(BINARY_STRING_CONVERSION_PROPERTY) != null && System.getenv(BINARY_STRING_CONVERSION_PROPERTY).equals(BynaryStringConversion.BINARY_STRING_CONVERSION_BASE64.toString()))) { return Base64.getDecoder().decode((String) value); } return value.toString().getBytes(); } else { return value.toString().getBytes(); } } catch (Exception e) { } } return null; } public ByteArraySchema _enum(List _enum) { super.setEnum(_enum); return this; } public ByteArraySchema addEnumItem(byte[] _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ByteArraySchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/ComposedSchema.java ================================================ package io.swagger.v3.oas.models.media; /** * ComposedSchema */ public class ComposedSchema extends Schema { public static ComposedSchema from(Schema subtypeModel) { ComposedSchema composedSchema = new ComposedSchema(); copySchemaProperties(composedSchema, subtypeModel); if (shouldSetExample(subtypeModel)) { composedSchema.example(subtypeModel.getExample()); } composedSchema.setEnum(subtypeModel.getEnum()); return composedSchema; } private static void copySchemaProperties(ComposedSchema target, Schema source) { target.title(source.getTitle()) .name(source.getName()) .deprecated(source.getDeprecated()) .additionalProperties(source.getAdditionalProperties()) .description(source.getDescription()) .discriminator(source.getDiscriminator()) .exclusiveMaximum(source.getExclusiveMaximum()) .exclusiveMinimum(source.getExclusiveMinimum()) .externalDocs(source.getExternalDocs()) .format(source.getFormat()) .maximum(source.getMaximum()) .maxItems(source.getMaxItems()) .maxLength(source.getMaxLength()) .maxProperties(source.getMaxProperties()) .minimum(source.getMinimum()) .minItems(source.getMinItems()) .minLength(source.getMinLength()) .minProperties(source.getMinProperties()) .multipleOf(source.getMultipleOf()) .not(source.getNot()) .nullable(source.getNullable()) .pattern(source.getPattern()) .properties(source.getProperties()) .readOnly(source.getReadOnly()) .required(source.getRequired()) .type(source.getType()) .uniqueItems(source.getUniqueItems()) .writeOnly(source.getWriteOnly()) .xml(source.getXml()) .extensions(source.getExtensions()); } private static boolean shouldSetExample(Schema model) { return model.getExample() != null || model.getExampleSetFlag(); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ComposedSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Content.java ================================================ package io.swagger.v3.oas.models.media; import java.util.LinkedHashMap; import java.util.Objects; /** * Content * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#content-object" */ public class Content extends LinkedHashMap { public Content() { } public Content addMediaType(String name, MediaType item) { this.put(name, item); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Content {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/DateSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Objects; /** * DateSchema */ public class DateSchema extends Schema { public DateSchema() { super("string", "date"); } @Override public DateSchema type(String type) { super.setType(type); return this; } @Override public DateSchema format(String format) { super.setFormat(format); return this; } public DateSchema _default(Date _default) { super.setDefault(_default); return this; } @Override protected Date cast(Object value) { if (value != null) { try { if (value instanceof Date) { return (Date) value; } else if (value instanceof String) { return new SimpleDateFormat("yyyy-MM-dd Z").parse((String)value + " UTC"); } } catch (Exception e) { } } return null; } public DateSchema addEnumItem(Date _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class DateSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/DateTimeSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.Date; import java.util.List; import java.util.Objects; /** * DateTimeSchema */ public class DateTimeSchema extends Schema { public DateTimeSchema() { super("string", "date-time"); } @Override public DateTimeSchema type(String type) { super.setType(type); return this; } @Override public DateTimeSchema format(String format) { super.setFormat(format); return this; } public DateTimeSchema _default(Date _default) { super.setDefault(_default); return this; } @Override protected OffsetDateTime cast(Object value) { if (value != null) { try { if (value instanceof Date) { return ((Date)value).toInstant().atOffset(ZoneOffset.UTC); } else if (value instanceof String) { return OffsetDateTime.parse((String)value); } else if (value instanceof OffsetDateTime) { return (OffsetDateTime)value; } } catch (Exception e) { } } return null; } public DateTimeSchema _enum(List _enum) { super.setEnum(_enum); return this; } public DateTimeSchema addEnumItem(OffsetDateTime _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class DateTimeSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Discriminator.java ================================================ package io.swagger.v3.oas.models.media; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; public class Discriminator { private String propertyName; private Map mapping; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Map extensions; public Discriminator propertyName(String propertyName) { this.propertyName = propertyName; return this; } public String getPropertyName() { return propertyName; } public void setPropertyName(String propertyName) { this.propertyName = propertyName; } public Discriminator mapping(String name, String value) { if (this.mapping == null) { this.mapping = new LinkedHashMap<>(); } this.mapping.put(name, value); return this; } public Discriminator mapping(Map mapping) { this.mapping = mapping; return this; } public Map getMapping() { return mapping; } public void setMapping(Map mapping) { this.mapping = mapping; } /** * returns the specific extensions from a Discriminator instance. * * @since 2.2.0 (OpenAPI 3.1.0) * @return Map<String, Object> extensions **/ @OpenAPI31 public Map getExtensions() { return extensions; } @OpenAPI31 public void setExtensions(Map extensions) { this.extensions = extensions; } @OpenAPI31 public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (name.startsWith("x-oas-") || name.startsWith("x-oai-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof Discriminator)) { return false; } Discriminator that = (Discriminator) o; if (propertyName != null ? !propertyName.equals(that.propertyName) : that.propertyName != null) { return false; } if (extensions != null ? !extensions.equals(that.extensions) : that.extensions != null) { return false; } return mapping != null ? mapping.equals(that.mapping) : that.mapping == null; } @Override public int hashCode() { return Objects.hash(propertyName, mapping, extensions); } @Override public String toString() { return "Discriminator{" + "propertyName='" + propertyName + '\'' + ", mapping=" + mapping + ", extensions=" + extensions + '}'; } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/EmailSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.Objects; /** * EmailSchema */ public class EmailSchema extends Schema { public EmailSchema() { super("string", "email"); } @Override public EmailSchema type(String type) { super.setType(type); return this; } @Override public EmailSchema format(String format) { super.setFormat(format); return this; } public EmailSchema _default(String _default) { super.setDefault(_default); return this; } @Override protected String cast(Object value) { if (value != null) { try { return value.toString(); } catch (Exception e) { } } return null; } public EmailSchema addEnumItem(String _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class EmailSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Encoding.java ================================================ package io.swagger.v3.oas.models.media; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.headers.Header; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * Encoding * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#encoding-object" */ public class Encoding { private String contentType; private Map headers; private StyleEnum style; private Boolean explode; private Boolean allowReserved; private java.util.Map extensions = null; public enum StyleEnum { FORM("form"), SPACE_DELIMITED("spaceDelimited"), PIPE_DELIMITED("pipeDelimited"), DEEP_OBJECT("deepObject"); private String value; StyleEnum(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } public static StyleEnum fromString(String value) { for (StyleEnum e : values()) { if (e.value.equals(value)) { return e; } } return null; } } public Encoding() { } public Encoding contentType(String contentType) { this.contentType = contentType; return this; } public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } public Encoding headers(Map headers) { this.headers = headers; return this; } public Map getHeaders() { return headers; } public void setHeaders(Map headers) { this.headers = headers; } public Encoding addHeader(String name, Header header) { if (this.headers == null) { this.headers = new LinkedHashMap<>(); } this.headers.put(name, header); return this; } public Encoding style(StyleEnum style) { this.style = style; return this; } public StyleEnum getStyle() { return style; } public void setStyle(StyleEnum style) { this.style = style; } public Encoding explode(Boolean explode) { this.explode = explode; return this; } public Boolean getExplode() { return explode; } public void setExplode(Boolean explode) { this.explode = explode; } public Encoding allowReserved(Boolean allowReserved) { this.allowReserved = allowReserved; return this; } public Boolean getAllowReserved() { return allowReserved; } public void setAllowReserved(Boolean allowReserved) { this.allowReserved = allowReserved; } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Encoding extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Encoding encoding = (Encoding) o; return Objects.equals(this.contentType, encoding.contentType) && Objects.equals(this.headers, encoding.headers) && Objects.equals(this.style, encoding.style) && Objects.equals(this.explode, encoding.explode) && Objects.equals(this.extensions, encoding.extensions) && Objects.equals(this.allowReserved, encoding.allowReserved); } @Override public int hashCode() { return Objects.hash(contentType, headers, style, explode, allowReserved, extensions); } @Override public String toString() { return "Encoding{" + "contentType='" + contentType + '\'' + ", headers=" + headers + ", style='" + style + '\'' + ", explode=" + explode + ", allowReserved=" + allowReserved + ", extensions=" + extensions + '}'; } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/EncodingProperty.java ================================================ package io.swagger.v3.oas.models.media; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.headers.Header; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * EncodingProperty * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#encoding-property-object" */ public class EncodingProperty { private String contentType = null; private Map headers = null; /** * Gets or Sets style */ public enum StyleEnum { FORM("form"), SPACEDELIMITED("spaceDelimited"), PIPEDELIMITED("pipeDelimited"), DEEPOBJECT("deepObject"); private String value; StyleEnum(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } private StyleEnum style = null; private Boolean explode = null; private Boolean allowReserved = null; private java.util.Map extensions = null; /** * returns the contentType property from a EncodingProperty instance. * * @return String contentType **/ public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } public EncodingProperty contentType(String contentType) { this.contentType = contentType; return this; } /** * returns the headers property from a EncodingProperty instance. * * @return headers **/ public Map getHeaders() { return headers; } public void setHeaders(Map headers) { this.headers = headers; } public EncodingProperty headers(Map headers) { this.headers = headers; return this; } public EncodingProperty addHeaderObject(String name, Header header) { if (this.headers == null) { headers = new LinkedHashMap<>(); } headers.put(name, header); return this; } /** * returns the style property from a EncodingProperty instance. * * @return StyleEnum style **/ public StyleEnum getStyle() { return style; } public void setStyle(StyleEnum style) { this.style = style; } public EncodingProperty style(StyleEnum style) { this.style = style; return this; } /** * returns the explode property from a EncodingProperty instance. * * @return Boolean explode **/ public Boolean getExplode() { return explode; } public void setExplode(Boolean explode) { this.explode = explode; } public EncodingProperty explode(Boolean explode) { this.explode = explode; return this; } /** * returns the allowReserved property from a EncodingProperty instance. * * @return Boolean allowReserved **/ public Boolean getAllowReserved() { return allowReserved; } public void setAllowReserved(Boolean allowReserved) { this.allowReserved = allowReserved; } public EncodingProperty allowReserved(Boolean allowReserved) { this.allowReserved = allowReserved; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } EncodingProperty encodingProperty = (EncodingProperty) o; return Objects.equals(this.contentType, encodingProperty.contentType) && Objects.equals(this.headers, encodingProperty.headers) && Objects.equals(this.style, encodingProperty.style) && Objects.equals(this.explode, encodingProperty.explode) && Objects.equals(this.allowReserved, encodingProperty.allowReserved) && Objects.equals(this.extensions, encodingProperty.extensions); } @Override public int hashCode() { return Objects.hash(contentType, headers, style, explode, allowReserved, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public EncodingProperty extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class EncodingProperty {\n"); sb.append(" contentType: ").append(toIndentedString(contentType)).append("\n"); sb.append(" headers: ").append(toIndentedString(headers)).append("\n"); sb.append(" style: ").append(toIndentedString(style)).append("\n"); sb.append(" explode: ").append(toIndentedString(explode)).append("\n"); sb.append(" allowReserved: ").append(toIndentedString(allowReserved)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/FileSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.Objects; /** * FileSchema */ public class FileSchema extends Schema { public FileSchema() { super("string", "binary"); } @Override public FileSchema type(String type) { super.setType(type); return this; } @Override public FileSchema format(String format) { super.setFormat(format); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class FileSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/IntegerSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.text.NumberFormat; import java.util.Objects; /** * IntegerSchema */ public class IntegerSchema extends Schema { public IntegerSchema() { super("integer", "int32"); } @Override public IntegerSchema type(String type) { super.setType(type); return this; } @Override public IntegerSchema format(String format) { super.setFormat(format); return this; } public IntegerSchema _default(Number _default) { super.setDefault(_default); return this; } @Override protected Number cast(Object value) { if (value != null) { try { Number casted = NumberFormat.getInstance().parse(value.toString()); if (Integer.MIN_VALUE <= casted.longValue() && casted.longValue() <= Integer.MAX_VALUE) { return Integer.parseInt(value.toString()); } else { return Long.parseLong(value.toString()); } } catch (Exception e) { } } return null; } public IntegerSchema addEnumItem(Number _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class IntegerSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/JsonSchema.java ================================================ package io.swagger.v3.oas.models.media; import io.swagger.v3.oas.models.SpecVersion; import java.text.NumberFormat; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * JsonSchema */ public class JsonSchema extends Schema { private static final Set NUMBER_TYPES = new HashSet<>(Arrays.asList("integer", "number")); public JsonSchema (){ specVersion(SpecVersion.V31); } private String resolveType() { if (this.getTypes() != null) { if (this.getTypes().size() == 1) { String type = this.getTypes().iterator().next(); if (NUMBER_TYPES.contains(type)) { return "number"; } return type; } if (this.getTypes().contains("object")) { return "object"; } else if (this.getTypes().contains("string")) { return "string"; } else if (this.getTypes().contains("array")) { return "array"; } else if (this.getTypes().contains("integer") || this.getTypes().contains("number")) { return "number"; } else if (this.getTypes().contains("boolean")) { return "boolean"; } return this.getTypes().iterator().next(); } return "null"; } protected Object cast(Object value) { if (value == null) { return null; } if (value instanceof String) { if (resolveType().equals("number")) { try { Number casted = NumberFormat.getInstance().parse(value.toString()); if (Integer.MIN_VALUE <= casted.longValue() && casted.longValue() <= Integer.MAX_VALUE) { return Integer.parseInt(value.toString()); } else { return Long.parseLong(value.toString()); } } catch (Exception e) { return value; } } else if (resolveType().equals("boolean")) { return Boolean.parseBoolean(value.toString()); } } return value; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class JsonSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/MapSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.Objects; /** * MapSchema */ public class MapSchema extends Schema { public MapSchema() { super("object", null); } @Override public MapSchema type(String type) { super.setType(type); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class MapSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/MediaType.java ================================================ package io.swagger.v3.oas.models.media; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.examples.Example; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * MediaType * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#media-type-object" */ public class MediaType { private Schema schema = null; private Map examples = null; private Object example = null; private Map encoding = null; private java.util.Map extensions = null; private boolean exampleSetFlag; /** * returns the schema property from a MediaType instance. * * @return Schema schema **/ public Schema getSchema() { return schema; } public void setSchema(Schema schema) { this.schema = schema; } public MediaType schema(Schema schema) { this.schema = schema; return this; } /** * returns the examples property from a MediaType instance. * * @return Map<String, Example> examples **/ public Map getExamples() { return examples; } public void setExamples(Map examples) { this.examples = examples; } public MediaType examples(Map examples) { this.examples = examples; return this; } public MediaType addExamples(String key, Example examplesItem) { if (this.examples == null) { this.examples = new LinkedHashMap<>(); } this.examples.put(key, examplesItem); return this; } /** * returns the example property from a MediaType instance. * * @return String example **/ public Object getExample() { return example; } public void setExample(Object example) { if (this.schema == null) { this.example = example; this.exampleSetFlag = true; return; } this.example = this.schema.cast(example); if (!(example != null && this.example == null)) { this.exampleSetFlag = true; } } public MediaType example(Object example) { setExample(example); return this; } /** * returns the encoding property from a MediaType instance. * * @return Encoding encoding **/ public Map getEncoding() { return encoding; } public void setEncoding(Map encoding) { this.encoding = encoding; } public MediaType encoding(Map encoding) { this.encoding = encoding; return this; } public MediaType addEncoding(String key, Encoding encodingItem) { if (this.encoding == null) { this.encoding = new LinkedHashMap<>(); } this.encoding.put(key, encodingItem); return this; } public boolean getExampleSetFlag() { return exampleSetFlag; } public void setExampleSetFlag(boolean exampleSetFlag) { this.exampleSetFlag = exampleSetFlag; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } MediaType mediaType = (MediaType) o; return Objects.equals(this.schema, mediaType.schema) && Objects.equals(this.examples, mediaType.examples) && Objects.equals(this.example, mediaType.example) && Objects.equals(this.encoding, mediaType.encoding) && Objects.equals(this.extensions, mediaType.extensions); } @Override public int hashCode() { return Objects.hash(schema, examples, example, encoding, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public MediaType extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class MediaType {\n"); sb.append(" schema: ").append(toIndentedString(schema)).append("\n"); sb.append(" examples: ").append(toIndentedString(examples)).append("\n"); sb.append(" example: ").append(toIndentedString(example)).append("\n"); sb.append(" encoding: ").append(toIndentedString(encoding)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/NumberSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.math.BigDecimal; import java.util.List; import java.util.Objects; /** * NumberSchema */ public class NumberSchema extends Schema { public NumberSchema() { super("number", null); } @Override public NumberSchema type(String type) { super.setType(type); return this; } public NumberSchema _default(BigDecimal _default) { super.setDefault(_default); return this; } public NumberSchema _enum(List _enum) { super.setEnum(_enum); return this; } public NumberSchema addEnumItem(BigDecimal _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override protected BigDecimal cast(Object value) { if (value != null) { try { return new BigDecimal(value.toString()); } catch (Exception e) { } } return null; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class NumberSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/ObjectSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.Objects; /** * ObjectSchema */ public class ObjectSchema extends Schema { public ObjectSchema() { super("object", null); } @Override public ObjectSchema type(String type) { super.setType(type); return this; } @Override public ObjectSchema example(Object example) { if (example != null) { super.setExample(example.toString()); } else { super.setExample(example); } return this; } @Override protected Object cast(Object value) { return value; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ObjectSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/PasswordSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.Objects; /** * PasswordSchema */ public class PasswordSchema extends Schema { public PasswordSchema() { super("string", "password"); } @Override public PasswordSchema type(String type) { super.setType(type); return this; } @Override public PasswordSchema format(String format) { super.setFormat(format); return this; } public PasswordSchema _default(String _default) { super.setDefault(_default); return this; } @Override protected String cast(Object value) { if (value != null) { try { return value.toString(); } catch (Exception e) { } } return null; } public PasswordSchema addEnumItem(String _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class PasswordSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/Schema.java ================================================ package io.swagger.v3.oas.models.media; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.models.annotations.OpenAPI30; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.ExternalDocumentation; import io.swagger.v3.oas.models.SpecVersion; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; /** * Schema * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#schema-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#schema-object" */ public class Schema { public static final String BIND_TYPE_AND_TYPES = "bind-type"; public static final String BINARY_STRING_CONVERSION_PROPERTY = "binary-string-conversion"; public enum BynaryStringConversion { BINARY_STRING_CONVERSION_BASE64("base64"), BINARY_STRING_CONVERSION_DEFAULT_CHARSET("default"), BINARY_STRING_CONVERSION_STRING_SCHEMA("string-schema"); private String value; BynaryStringConversion(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } public static final String SCHEMA_RESOLUTION_PROPERTY = "schema-resolution"; public static final String APPLY_SCHEMA_RESOLUTION_PROPERTY = "apply-schema-resolution"; public static final String EXPLICIT_OBJECT_SCHEMA_PROPERTY = "explicit-object-schema"; public static final String USE_ARBITRARY_SCHEMA_PROPERTY = "use-arbitrary-schema"; public enum SchemaResolution { @JsonProperty("default") DEFAULT("default"), @JsonProperty("inline") INLINE("inline"), @JsonProperty("all-of") ALL_OF("all-of"), @JsonProperty("all-of-ref") ALL_OF_REF("all-of-ref"); private String value; SchemaResolution(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } protected T _default; private String name; private String title = null; private BigDecimal multipleOf = null; private BigDecimal maximum = null; @OpenAPI30 private Boolean exclusiveMaximum = null; private BigDecimal minimum = null; @OpenAPI30 private Boolean exclusiveMinimum = null; private Integer maxLength = null; private Integer minLength = null; private String pattern = null; private Integer maxItems = null; private Integer minItems = null; private Boolean uniqueItems = null; private Integer maxProperties = null; private Integer minProperties = null; private List required = null; @OpenAPI30 private String type = null; private Schema not = null; private Map properties = null; private Object additionalProperties = null; private String description = null; private String format = null; private String $ref = null; @OpenAPI30 private Boolean nullable = null; private Boolean readOnly = null; private Boolean writeOnly = null; protected T example = null; private ExternalDocumentation externalDocs = null; private Boolean deprecated = null; private XML xml = null; private java.util.Map extensions = null; protected List _enum = null; private Discriminator discriminator = null; @JsonIgnore private boolean exampleSetFlag; @JsonIgnore private boolean defaultSetFlag; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private List prefixItems = null; private List allOf = null; private List anyOf = null; private List oneOf = null; private Schema items = null; protected T _const; private SpecVersion specVersion = SpecVersion.V30; @JsonIgnore public SpecVersion getSpecVersion() { return this.specVersion; } public void setSpecVersion(SpecVersion specVersion) { this.specVersion = specVersion; } public Schema specVersion(SpecVersion specVersion) { this.setSpecVersion(specVersion); return this; } /* @OpenAPI31 fields and accessors */ /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Set types; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Map patternProperties = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private BigDecimal exclusiveMaximumValue = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private BigDecimal exclusiveMinimumValue = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Schema contains = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private String $id; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private String $schema; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private String $anchor; /** * @since 2.2.14 (OpenAPI 3.1.0) */ @OpenAPI31 private String $vocabulary; /** * @since 2.2.14 (OpenAPI 3.1.0) */ @OpenAPI31 private String $dynamicAnchor; /** * @since 2.2.32 (OpenAPI 3.1.0) */ @OpenAPI31 private String $dynamicRef; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private String contentEncoding; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private String contentMediaType; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Schema contentSchema; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Schema propertyNames; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Schema unevaluatedProperties; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Integer maxContains; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Integer minContains; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Schema additionalItems; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Schema unevaluatedItems; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Schema _if; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Schema _else; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Schema then; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Map dependentSchemas; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private Map> dependentRequired; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private String $comment; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 private List examples; /** * @since 2.2.2 (OpenAPI 3.1.0) * * when set, this represents a boolean schema value */ @OpenAPI31 private Boolean booleanSchemaValue; /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema getContains() { return contains; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setContains(Schema contains) { this.contains = contains; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public String get$id() { return $id; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void set$id(String $id) { this.$id = $id; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public String get$schema() { return $schema; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void set$schema(String $schema) { this.$schema = $schema; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public String get$anchor() { return $anchor; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void set$anchor(String $anchor) { this.$anchor = $anchor; } /** * returns the exclusiveMaximumValue property from a Schema instance for OpenAPI 3.1.x * * @since 2.2.0 (OpenAPI 3.1.0) * @return BigDecimal exclusiveMaximumValue * **/ @OpenAPI31 public BigDecimal getExclusiveMaximumValue() { return exclusiveMaximumValue; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setExclusiveMaximumValue(BigDecimal exclusiveMaximumValue) { this.exclusiveMaximumValue = exclusiveMaximumValue; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema exclusiveMaximumValue(BigDecimal exclusiveMaximumValue) { this.exclusiveMaximumValue = exclusiveMaximumValue; return this; } /** * returns the exclusiveMinimumValue property from a Schema instance for OpenAPI 3.1.x * * @since 2.2.0 (OpenAPI 3.1.0) * @return BigDecimal exclusiveMinimumValue * **/ @OpenAPI31 public BigDecimal getExclusiveMinimumValue() { return exclusiveMinimumValue; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setExclusiveMinimumValue(BigDecimal exclusiveMinimumValue) { this.exclusiveMinimumValue = exclusiveMinimumValue; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema exclusiveMinimumValue(BigDecimal exclusiveMinimumValue) { this.exclusiveMinimumValue = exclusiveMinimumValue; return this; } /** * returns the patternProperties property from a Schema instance. * * @since 2.2.0 (OpenAPI 3.1.0) * @return Map<String, Schema> patternProperties **/ @OpenAPI31 public Map getPatternProperties() { return patternProperties; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setPatternProperties(Map patternProperties) { this.patternProperties = patternProperties; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema patternProperties(Map patternProperties) { this.patternProperties = patternProperties; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema addPatternProperty(String key, Schema patternPropertiesItem) { if (this.patternProperties == null) { this.patternProperties = new LinkedHashMap<>(); } this.patternProperties.put(key, patternPropertiesItem); return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema contains(Schema contains) { this.contains = contains; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema $id(String $id) { this.$id = $id; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Set getTypes() { return types; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setTypes(Set types) { this.types = types; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public boolean addType(String type) { if (types == null) { types = new LinkedHashSet<>(); } return types.add(type); } /** * * @since 2.2.30 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema typesItem(String type) { addType(type); return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema $schema(String $schema) { this.$schema = $schema; return this; } /** * * @since 2.2.8 (OpenAPI 3.1.0) */ @OpenAPI31 public String get$vocabulary() { return $vocabulary; } /** * * @since 2.2.8 (OpenAPI 3.1.0) */ @OpenAPI31 public void set$vocabulary(String $vocabulary) { this.$vocabulary = $vocabulary; } /** * * @since 2.2.8 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema $vocabulary(String $vocabulary) { this.$vocabulary = $vocabulary; return this; } /** * * @since 2.2.8 (OpenAPI 3.1.0) */ @OpenAPI31 public String get$dynamicAnchor() { return $dynamicAnchor; } /** * * @since 2.2.8 (OpenAPI 3.1.0) */ @OpenAPI31 public void set$dynamicAnchor(String $dynamicAnchor) { this.$dynamicAnchor = $dynamicAnchor; } /** * * @since 2.2.8 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema $dynamicAnchor(String $dynamicAnchor) { this.$dynamicAnchor = $dynamicAnchor; return this; } /** * * @since 2.2.32 (OpenAPI 3.1.0) */ @OpenAPI31 public String get$dynamicRef() { return $dynamicRef; } /** * * @since 2.2.32 (OpenAPI 3.1.0) */ @OpenAPI31 public void set$dynamicRef(String $dynamicRef) { this.$dynamicRef = $dynamicRef; } /** * * @since 2.2.32 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema $dynamicRef(String $dynamicRef) { this.$dynamicRef = $dynamicRef; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema $anchor(String $anchor) { this.$anchor = $anchor; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema types(Set types) { this.types = types; return this; } /* INTERNAL MEMBERS @OpenAPI31 */ /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 protected Map jsonSchema = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Map getJsonSchema() { return jsonSchema; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setJsonSchema(Map jsonSchema) { this.jsonSchema = jsonSchema; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema jsonSchema(Map jsonSchema) { this.jsonSchema = jsonSchema; return this; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 protected transient Object jsonSchemaImpl = null; /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Object getJsonSchemaImpl() { return jsonSchemaImpl; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setJsonSchemaImpl(Object jsonSchemaImpl) { this.jsonSchemaImpl = jsonSchemaImpl; } /** * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema jsonSchemaImpl(Object jsonSchemaImpl) { setJsonSchemaImpl(jsonSchemaImpl); return this; } /* CONSTRUCTORS */ public Schema() { } protected Schema(String type, String format) { this.type = type; this.addType(type); this.format = format; } public Schema(SpecVersion specVersion) { this.specVersion = specVersion; } protected Schema(String type, String format, SpecVersion specVersion) { this.type = type; this.addType(type); this.format = format; this.specVersion = specVersion; } /* ACCESSORS */ /** * returns the allOf property from a ComposedSchema instance. * * @return List<Schema> allOf **/ public List getAllOf() { return allOf; } public void setAllOf(List allOf) { this.allOf = allOf; } public Schema allOf(List allOf) { this.allOf = allOf; return this; } public Schema addAllOfItem(Schema allOfItem) { if (this.allOf == null) { this.allOf = new ArrayList<>(); } this.allOf.add(allOfItem); return this; } /** * returns the anyOf property from a ComposedSchema instance. * * @return List<Schema> anyOf **/ public List getAnyOf() { return anyOf; } public void setAnyOf(List anyOf) { this.anyOf = anyOf; } public Schema anyOf(List anyOf) { this.anyOf = anyOf; return this; } public Schema addAnyOfItem(Schema anyOfItem) { if (this.anyOf == null) { this.anyOf = new ArrayList<>(); } this.anyOf.add(anyOfItem); return this; } /** * returns the oneOf property from a ComposedSchema instance. * * @return List<Schema> oneOf **/ public List getOneOf() { return oneOf; } public void setOneOf(List oneOf) { this.oneOf = oneOf; } public Schema oneOf(List oneOf) { this.oneOf = oneOf; return this; } public Schema addOneOfItem(Schema oneOfItem) { if (this.oneOf == null) { this.oneOf = new ArrayList<>(); } this.oneOf.add(oneOfItem); return this; } /** * returns the items property from a ArraySchema instance. * * @return Schema items **/ public Schema getItems() { return items; } public void setItems(Schema items) { this.items = items; } public Schema items(Schema items) { this.items = items; return this; } /** * returns the name property from a Schema instance. Ignored in serialization. * * @return String name **/ @JsonIgnore public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Schema name(String name) { this.setName(name); return this; } /** * returns the discriminator property from a AllOfSchema instance. * * @return Discriminator discriminator **/ public Discriminator getDiscriminator() { return discriminator; } public void setDiscriminator(Discriminator discriminator) { this.discriminator = discriminator; } public Schema discriminator(Discriminator discriminator) { this.discriminator = discriminator; return this; } /** * returns the title property from a Schema instance. * * @return String title **/ public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Schema title(String title) { this.title = title; return this; } /** * returns the _default property from a Schema instance. * * @return String _default **/ public T getDefault() { return _default; } public void setDefault(Object _default) { this._default = cast(_default); if (!(_default != null && this._default == null)) { defaultSetFlag = true; } } @SuppressWarnings("unchecked") protected T cast(Object value) { return (T) value; } public List getEnum() { return _enum; } public void setEnum(List _enum) { this._enum = _enum; } public void addEnumItemObject(T _enumItem) { if (this._enum == null) { this._enum = new ArrayList<>(); } this._enum.add(cast(_enumItem)); } /** * returns the multipleOf property from a Schema instance. *

    * minimum: 0 * * @return BigDecimal multipleOf **/ public BigDecimal getMultipleOf() { return multipleOf; } public void setMultipleOf(BigDecimal multipleOf) { this.multipleOf = multipleOf; } public Schema multipleOf(BigDecimal multipleOf) { this.multipleOf = multipleOf; return this; } /** * returns the maximum property from a Schema instance. * * @return BigDecimal maximum **/ public BigDecimal getMaximum() { return maximum; } public void setMaximum(BigDecimal maximum) { this.maximum = maximum; } public Schema maximum(BigDecimal maximum) { this.maximum = maximum; return this; } /** * returns the exclusiveMaximum property from a Schema instance for OpenAPI 3.0.x * * @return Boolean exclusiveMaximum **/ @OpenAPI30 public Boolean getExclusiveMaximum() { return exclusiveMaximum; } @OpenAPI30 public void setExclusiveMaximum(Boolean exclusiveMaximum) { this.exclusiveMaximum = exclusiveMaximum; } @OpenAPI30 public Schema exclusiveMaximum(Boolean exclusiveMaximum) { this.exclusiveMaximum = exclusiveMaximum; return this; } /** * returns the minimum property from a Schema instance. * * @return BigDecimal minimum **/ public BigDecimal getMinimum() { return minimum; } public void setMinimum(BigDecimal minimum) { this.minimum = minimum; } public Schema minimum(BigDecimal minimum) { this.minimum = minimum; return this; } /** * returns the exclusiveMinimum property from a Schema instance for OpenAPI 3.0.x * * @return Boolean exclusiveMinimum **/ public Boolean getExclusiveMinimum() { return exclusiveMinimum; } public void setExclusiveMinimum(Boolean exclusiveMinimum) { this.exclusiveMinimum = exclusiveMinimum; } public Schema exclusiveMinimum(Boolean exclusiveMinimum) { this.exclusiveMinimum = exclusiveMinimum; return this; } /** * returns the maxLength property from a Schema instance. *

    * minimum: 0 * * @return Integer maxLength **/ public Integer getMaxLength() { return maxLength; } public void setMaxLength(Integer maxLength) { this.maxLength = maxLength; } public Schema maxLength(Integer maxLength) { this.maxLength = maxLength; return this; } /** * returns the minLength property from a Schema instance. *

    * minimum: 0 * * @return Integer minLength **/ public Integer getMinLength() { return minLength; } public void setMinLength(Integer minLength) { this.minLength = minLength; } public Schema minLength(Integer minLength) { this.minLength = minLength; return this; } /** * returns the pattern property from a Schema instance. * * @return String pattern **/ public String getPattern() { return pattern; } public void setPattern(String pattern) { this.pattern = pattern; } public Schema pattern(String pattern) { this.pattern = pattern; return this; } /** * returns the maxItems property from a Schema instance. *

    * minimum: 0 * * @return Integer maxItems **/ public Integer getMaxItems() { return maxItems; } public void setMaxItems(Integer maxItems) { this.maxItems = maxItems; } public Schema maxItems(Integer maxItems) { this.maxItems = maxItems; return this; } /** * returns the minItems property from a Schema instance. *

    * minimum: 0 * * @return Integer minItems **/ public Integer getMinItems() { return minItems; } public void setMinItems(Integer minItems) { this.minItems = minItems; } public Schema minItems(Integer minItems) { this.minItems = minItems; return this; } /** * returns the uniqueItems property from a Schema instance. * * @return Boolean uniqueItems **/ public Boolean getUniqueItems() { return uniqueItems; } public void setUniqueItems(Boolean uniqueItems) { this.uniqueItems = uniqueItems; } public Schema uniqueItems(Boolean uniqueItems) { this.uniqueItems = uniqueItems; return this; } /** * returns the maxProperties property from a Schema instance. *

    * minimum: 0 * * @return Integer maxProperties **/ public Integer getMaxProperties() { return maxProperties; } public void setMaxProperties(Integer maxProperties) { this.maxProperties = maxProperties; } public Schema maxProperties(Integer maxProperties) { this.maxProperties = maxProperties; return this; } /** * returns the minProperties property from a Schema instance. *

    * minimum: 0 * * @return Integer minProperties **/ public Integer getMinProperties() { return minProperties; } public void setMinProperties(Integer minProperties) { this.minProperties = minProperties; } public Schema minProperties(Integer minProperties) { this.minProperties = minProperties; return this; } /** * returns the required property from a Schema instance. * * @return List<String> required **/ public List getRequired() { return required; } public void setRequired(List required) { List list = new ArrayList<>(); if (required != null) { for (String req : required) { if (this.properties == null || this.properties.containsKey(req)) { list.add(req); } } } Collections.sort(list); if (list.isEmpty()) { list = null; } this.required = list; } public Schema required(List required) { this.required = required; return this; } public Schema addRequiredItem(String requiredItem) { if (this.required == null) { this.required = new ArrayList<>(); } this.required.add(requiredItem); Collections.sort(required); return this; } /** * returns the type property from a Schema instance. * * @return String type **/ public String getType() { boolean bindTypes = Boolean.valueOf(System.getProperty(BIND_TYPE_AND_TYPES, "false")); if (bindTypes && type == null && types != null && types.size() == 1) { return types.iterator().next(); } return type; } public void setType(String type) { this.type = type; } public Schema type(String type) { this.type = type; return this; } /** * returns the not property from a Schema instance. * * @return Schema not **/ public Schema getNot() { return not; } public void setNot(Schema not) { this.not = not; } public Schema not(Schema not) { this.not = not; return this; } /** * returns the properties property from a Schema instance. * * @return Map<String, Schema> properties **/ public Map getProperties() { return properties; } public void setProperties(Map properties) { this.properties = properties; } public Schema properties(Map properties) { this.properties = properties; return this; } @Deprecated public Schema addProperties(String key, Schema property) { return addProperty(key, property); } /** * * @since 2.2.0 */ public Schema addProperty(String key, Schema property) { if (this.properties == null) { this.properties = new LinkedHashMap<>(); } this.properties.put(key, property); return this; } /** * returns the additionalProperties property from a Schema instance. Can be either a Boolean or a Schema * * @return Object additionalProperties **/ public Object getAdditionalProperties() { return additionalProperties; } public void setAdditionalProperties(Object additionalProperties) { if (additionalProperties != null && !(additionalProperties instanceof Boolean) && !(additionalProperties instanceof Schema)) { throw new IllegalArgumentException("additionalProperties must be either a Boolean or a Schema instance"); } this.additionalProperties = additionalProperties; } public Schema additionalProperties(Object additionalProperties) { setAdditionalProperties(additionalProperties); return this; } /** * returns the description property from a Schema instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Schema description(String description) { this.description = description; return this; } /** * returns the format property from a Schema instance. * * @return String format **/ public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } public Schema format(String format) { this.format = format; return this; } /** * returns the $ref property from a Schema instance. * * @return String $ref **/ public String get$ref() { return $ref; } public void set$ref(String $ref) { if ($ref != null && !$ref.startsWith("#") && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { $ref = Components.COMPONENTS_SCHEMAS_REF + $ref; } this.$ref = $ref; } public Schema $ref(String $ref) { set$ref($ref); return this; } public Schema raw$ref(String $ref) { this.$ref = $ref; return this; } /** * returns the nullable property from a Schema instance. * * @return Boolean nullable **/ @OpenAPI30 public Boolean getNullable() { return nullable; } @OpenAPI30 public void setNullable(Boolean nullable) { this.nullable = nullable; } @OpenAPI30 public Schema nullable(Boolean nullable) { this.nullable = nullable; return this; } /** * returns the readOnly property from a Schema instance. * * @return Boolean readOnly **/ public Boolean getReadOnly() { return readOnly; } public void setReadOnly(Boolean readOnly) { this.readOnly = readOnly; } public Schema readOnly(Boolean readOnly) { this.readOnly = readOnly; return this; } /** * returns the writeOnly property from a Schema instance. * * @return Boolean writeOnly **/ public Boolean getWriteOnly() { return writeOnly; } public void setWriteOnly(Boolean writeOnly) { this.writeOnly = writeOnly; } public Schema writeOnly(Boolean writeOnly) { this.writeOnly = writeOnly; return this; } /** * returns the example property from a Schema instance. * * @return String example **/ public Object getExample() { return example; } public void setExample(Object example) { this.example = cast(example); if (!(example != null && this.example == null)) { exampleSetFlag = true; } } public Schema example(Object example) { setExample(example); return this; } /** * returns the externalDocs property from a Schema instance. * * @return ExternalDocumentation externalDocs **/ public ExternalDocumentation getExternalDocs() { return externalDocs; } public void setExternalDocs(ExternalDocumentation externalDocs) { this.externalDocs = externalDocs; } public Schema externalDocs(ExternalDocumentation externalDocs) { this.externalDocs = externalDocs; return this; } /** * returns the deprecated property from a Schema instance. * * @return Boolean deprecated **/ public Boolean getDeprecated() { return deprecated; } public void setDeprecated(Boolean deprecated) { this.deprecated = deprecated; } public Schema deprecated(Boolean deprecated) { this.deprecated = deprecated; return this; } /** * returns the xml property from a Schema instance. * * @return XML xml **/ public XML getXml() { return xml; } public void setXml(XML xml) { this.xml = xml; } public Schema xml(XML xml) { this.xml = xml; return this; } /** * returns true if example setter has been invoked * Used to flag explicit setting to null of example (vs missing field) while deserializing from json/yaml string * * @return boolean exampleSetFlag **/ public boolean getExampleSetFlag() { return exampleSetFlag; } public void setExampleSetFlag(boolean exampleSetFlag) { this.exampleSetFlag = exampleSetFlag; } /** * returns true if default setter has been invoked * Used to flag explicit setting to null of default (vs missing field) while deserializing from json/yaml string * * @return boolean defaultSetFlag **/ public boolean getDefaultSetFlag() { return defaultSetFlag; } public void setDefaultSetFlag(boolean defaultSetFlag) { this.defaultSetFlag = defaultSetFlag; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public List getPrefixItems() { return prefixItems; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setPrefixItems(List prefixItems) { this.prefixItems = prefixItems; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema prefixItems(List prefixItems) { this.prefixItems = prefixItems; return this; } /** * * @since 2.2.12 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema addPrefixItem(Schema prefixItem) { if (this.prefixItems == null) { this.prefixItems = new ArrayList<>(); } this.prefixItems.add(prefixItem); return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public String getContentEncoding() { return contentEncoding; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setContentEncoding(String contentEncoding) { this.contentEncoding = contentEncoding; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema contentEncoding(String contentEncoding) { this.contentEncoding = contentEncoding; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public String getContentMediaType() { return contentMediaType; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setContentMediaType(String contentMediaType) { this.contentMediaType = contentMediaType; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema contentMediaType(String contentMediaType) { this.contentMediaType = contentMediaType; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema getContentSchema() { return contentSchema; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setContentSchema(Schema contentSchema) { this.contentSchema = contentSchema; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema contentSchema(Schema contentSchema) { this.contentSchema = contentSchema; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema getPropertyNames() { return propertyNames; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setPropertyNames(Schema propertyNames) { this.propertyNames = propertyNames; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema propertyNames(Schema propertyNames) { this.propertyNames = propertyNames; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema getUnevaluatedProperties() { return unevaluatedProperties; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setUnevaluatedProperties(Schema unevaluatedProperties) { this.unevaluatedProperties = unevaluatedProperties; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema unevaluatedProperties(Schema unevaluatedProperties) { this.unevaluatedProperties = unevaluatedProperties; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Integer getMaxContains() { return maxContains; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setMaxContains(Integer maxContains) { this.maxContains = maxContains; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema maxContains(Integer maxContains) { this.maxContains = maxContains; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Integer getMinContains() { return minContains; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setMinContains(Integer minContains) { this.minContains = minContains; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema minContains(Integer minContains) { this.minContains = minContains; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema getAdditionalItems() { return additionalItems; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setAdditionalItems(Schema additionalItems) { this.additionalItems = additionalItems; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema additionalItems(Schema additionalItems) { this.additionalItems = additionalItems; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema getUnevaluatedItems() { return unevaluatedItems; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setUnevaluatedItems(Schema unevaluatedItems) { this.unevaluatedItems = unevaluatedItems; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema unevaluatedItems(Schema unevaluatedItems) { this.unevaluatedItems = unevaluatedItems; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema getIf() { return _if; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setIf(Schema _if) { this._if = _if; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema _if(Schema _if) { this._if = _if; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema getElse() { return _else; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setElse(Schema _else) { this._else = _else; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema _else(Schema _else) { this._else = _else; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema getThen() { return then; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setThen(Schema then) { this.then = then; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema then(Schema then) { this.then = then; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Map getDependentSchemas() { return dependentSchemas; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setDependentSchemas(Map dependentSchemas) { this.dependentSchemas = dependentSchemas; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema dependentSchemas(Map dependentSchemas) { this.dependentSchemas = dependentSchemas; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Map> getDependentRequired() { return dependentRequired; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setDependentRequired(Map> dependentRequired) { this.dependentRequired = dependentRequired; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema dependentRequired(Map> dependentRequired) { this.dependentRequired = dependentRequired; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public String get$comment() { return $comment; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void set$comment(String $comment) { this.$comment = $comment; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema $comment(String $comment) { this.$comment = $comment; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public List getExamples() { return examples; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setExamples(List examples) { this.examples = examples; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema examples(List examples) { this.examples = examples; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void addExample(T example) { if (this.examples == null) { this.examples = new ArrayList<>(); } this.examples.add(example); } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Schema schema = (Schema) o; return Objects.equals(this.title, schema.title) && Objects.equals(this.multipleOf, schema.multipleOf) && Objects.equals(this.maximum, schema.maximum) && Objects.equals(this.exclusiveMaximum, schema.exclusiveMaximum) && Objects.equals(this.exclusiveMaximumValue, schema.exclusiveMaximumValue) && Objects.equals(this.minimum, schema.minimum) && Objects.equals(this.exclusiveMinimum, schema.exclusiveMinimum) && Objects.equals(this.exclusiveMinimumValue, schema.exclusiveMinimumValue) && Objects.equals(this.maxLength, schema.maxLength) && Objects.equals(this.minLength, schema.minLength) && Objects.equals(this.pattern, schema.pattern) && Objects.equals(this.maxItems, schema.maxItems) && Objects.equals(this.minItems, schema.minItems) && Objects.equals(this.uniqueItems, schema.uniqueItems) && Objects.equals(this.maxProperties, schema.maxProperties) && Objects.equals(this.minProperties, schema.minProperties) && Objects.equals(this.required, schema.required) && Objects.equals(this.type, schema.type) && Objects.equals(this.not, schema.not) && Objects.equals(this.properties, schema.properties) && Objects.equals(this.additionalProperties, schema.additionalProperties) && Objects.equals(this.description, schema.description) && Objects.equals(this.format, schema.format) && Objects.equals(this.$ref, schema.$ref) && Objects.equals(this.nullable, schema.nullable) && Objects.equals(this.readOnly, schema.readOnly) && Objects.equals(this.writeOnly, schema.writeOnly) && Objects.equals(this.example, schema.example) && Objects.equals(this.externalDocs, schema.externalDocs) && Objects.equals(this.deprecated, schema.deprecated) && Objects.equals(this.xml, schema.xml) && Objects.equals(this.extensions, schema.extensions) && Objects.equals(this.discriminator, schema.discriminator) && Objects.equals(this._enum, schema._enum) && Objects.equals(this.contains, schema.contains) && Objects.equals(this.patternProperties, schema.patternProperties) && Objects.equals(this.$id, schema.$id) && Objects.equals(this.$anchor, schema.$anchor) && Objects.equals(this.$schema, schema.$schema) && Objects.equals(this.$vocabulary, schema.$vocabulary) && Objects.equals(this.$dynamicAnchor, schema.$dynamicAnchor) && Objects.equals(this.$dynamicRef, schema.$dynamicRef) && Objects.equals(this.types, schema.types) && Objects.equals(this.allOf, schema.allOf) && Objects.equals(this.anyOf, schema.anyOf) && Objects.equals(this.oneOf, schema.oneOf) && Objects.equals(this._const, schema._const) && Objects.equals(this._default, schema._default) && Objects.equals(this.contentEncoding, schema.contentEncoding) && Objects.equals(this.contentMediaType, schema.contentMediaType) && Objects.equals(this.contentSchema, schema.contentSchema) && Objects.equals(this.propertyNames, schema.propertyNames) && Objects.equals(this.unevaluatedProperties, schema.unevaluatedProperties) && Objects.equals(this.maxContains, schema.maxContains) && Objects.equals(this.minContains, schema.minContains) && Objects.equals(this.additionalItems, schema.additionalItems) && Objects.equals(this.unevaluatedItems, schema.unevaluatedItems) && Objects.equals(this._if, schema._if) && Objects.equals(this._else, schema._else) && Objects.equals(this.then, schema.then) && Objects.equals(this.dependentRequired, schema.dependentRequired) && Objects.equals(this.dependentSchemas, schema.dependentSchemas) && Objects.equals(this.$comment, schema.$comment) && Objects.equals(this.examples, schema.examples) && Objects.equals(this.prefixItems, schema.prefixItems) && Objects.equals(this.items, schema.items) && Objects.equals(this.booleanSchemaValue, schema.booleanSchemaValue) ; } @Override public int hashCode() { return Objects.hash(title, multipleOf, maximum, exclusiveMaximum, exclusiveMaximumValue, minimum, exclusiveMinimum, exclusiveMinimumValue, maxLength, minLength, pattern, maxItems, minItems, uniqueItems, maxProperties, minProperties, required, type, not, properties, additionalProperties, description, format, $ref, nullable, readOnly, writeOnly, example, externalDocs, deprecated, xml, extensions, discriminator, _enum, _default, patternProperties, $id, $anchor, $schema, $vocabulary, $dynamicAnchor, $dynamicRef, types, allOf, anyOf, oneOf, _const, contentEncoding, contentMediaType, contentSchema, propertyNames, unevaluatedProperties, maxContains, minContains, additionalItems, unevaluatedItems, _if, _else, then, dependentRequired, dependentSchemas, $comment, examples, prefixItems, items, booleanSchemaValue); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || (specVersion == SpecVersion.V30 && !name.startsWith("x-"))) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Schema extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Schema {\n"); Object typeStr = specVersion == SpecVersion.V30 ? type : types; sb.append(" type: ").append(toIndentedString(typeStr)).append("\n"); sb.append(" format: ").append(toIndentedString(format)).append("\n"); sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" title: ").append(toIndentedString(title)).append("\n"); sb.append(" multipleOf: ").append(toIndentedString(multipleOf)).append("\n"); sb.append(" maximum: ").append(toIndentedString(maximum)).append("\n"); Object exclusiveMaximumStr = specVersion == SpecVersion.V30 ? exclusiveMaximum : exclusiveMaximumValue; sb.append(" exclusiveMaximum: ").append(toIndentedString(exclusiveMaximumStr)).append("\n"); sb.append(" minimum: ").append(toIndentedString(minimum)).append("\n"); Object exclusiveMinimumStr = specVersion == SpecVersion.V30 ? exclusiveMinimum : exclusiveMinimumValue; sb.append(" exclusiveMinimum: ").append(toIndentedString(exclusiveMinimumStr)).append("\n"); sb.append(" maxLength: ").append(toIndentedString(maxLength)).append("\n"); sb.append(" minLength: ").append(toIndentedString(minLength)).append("\n"); sb.append(" pattern: ").append(toIndentedString(pattern)).append("\n"); sb.append(" maxItems: ").append(toIndentedString(maxItems)).append("\n"); sb.append(" minItems: ").append(toIndentedString(minItems)).append("\n"); sb.append(" uniqueItems: ").append(toIndentedString(uniqueItems)).append("\n"); sb.append(" maxProperties: ").append(toIndentedString(maxProperties)).append("\n"); sb.append(" minProperties: ").append(toIndentedString(minProperties)).append("\n"); sb.append(" required: ").append(toIndentedString(required)).append("\n"); sb.append(" not: ").append(toIndentedString(not)).append("\n"); sb.append(" properties: ").append(toIndentedString(properties)).append("\n"); sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); sb.append(" nullable: ").append(toIndentedString(nullable)).append("\n"); sb.append(" readOnly: ").append(toIndentedString(readOnly)).append("\n"); sb.append(" writeOnly: ").append(toIndentedString(writeOnly)).append("\n"); sb.append(" example: ").append(toIndentedString(example)).append("\n"); sb.append(" externalDocs: ").append(toIndentedString(externalDocs)).append("\n"); sb.append(" deprecated: ").append(toIndentedString(deprecated)).append("\n"); sb.append(" discriminator: ").append(toIndentedString(discriminator)).append("\n"); sb.append(" xml: ").append(toIndentedString(xml)).append("\n"); if (specVersion == SpecVersion.V31) { sb.append(" patternProperties: ").append(toIndentedString(patternProperties)).append("\n"); sb.append(" contains: ").append(toIndentedString(contains)).append("\n"); sb.append(" $id: ").append(toIndentedString($id)).append("\n"); sb.append(" $anchor: ").append(toIndentedString($anchor)).append("\n"); sb.append(" $schema: ").append(toIndentedString($schema)).append("\n"); sb.append(" $vocabulary: ").append(toIndentedString($vocabulary)).append("\n"); sb.append(" $dynamicAnchor: ").append(toIndentedString($dynamicAnchor)).append("\n"); sb.append(" $dynamicRef: ").append(toIndentedString($dynamicRef)).append("\n"); sb.append(" const: ").append(toIndentedString(_const)).append("\n"); sb.append(" contentEncoding: ").append(toIndentedString(contentEncoding)).append("\n"); sb.append(" contentMediaType: ").append(toIndentedString(contentMediaType)).append("\n"); sb.append(" contentSchema: ").append(toIndentedString(contentSchema)).append("\n"); sb.append(" propertyNames: ").append(toIndentedString(propertyNames)).append("\n"); sb.append(" unevaluatedProperties: ").append(toIndentedString(unevaluatedProperties)).append("\n"); sb.append(" maxContains: ").append(toIndentedString(maxContains)).append("\n"); sb.append(" minContains: ").append(toIndentedString(minContains)).append("\n"); sb.append(" additionalItems: ").append(toIndentedString(additionalItems)).append("\n"); sb.append(" unevaluatedItems: ").append(toIndentedString(unevaluatedItems)).append("\n"); sb.append(" _if: ").append(toIndentedString(_if)).append("\n"); sb.append(" _else: ").append(toIndentedString(_else)).append("\n"); sb.append(" then: ").append(toIndentedString(then)).append("\n"); sb.append(" dependentRequired: ").append(toIndentedString(dependentRequired)).append("\n"); sb.append(" dependentSchemas: ").append(toIndentedString(dependentSchemas)).append("\n"); sb.append(" $comment: ").append(toIndentedString($comment)).append("\n"); sb.append(" prefixItems: ").append(toIndentedString(prefixItems)).append("\n"); sb.append(" booleanSchemaValue: ").append(toIndentedString(booleanSchemaValue)).append("\n"); } sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ protected String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } public Schema _default(T _default) { this._default = _default; return this; } public Schema _enum(List _enum) { this._enum = _enum; return this; } public Schema exampleSetFlag(boolean exampleSetFlag) { this.exampleSetFlag = exampleSetFlag; return this; } public Schema defaultSetFlag(boolean defaultSetFlag) { this.defaultSetFlag = defaultSetFlag; return this; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public T getConst() { return _const; } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public void setConst(Object _const) { this._const = cast(_const); } /** * * @since 2.2.0 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema _const(Object _const) { this._const = cast(_const); return this; } /** * * @since 2.2.2 (OpenAPI 3.1.0) */ @OpenAPI31 public Boolean getBooleanSchemaValue() { return booleanSchemaValue; } /** * * @since 2.2.2 (OpenAPI 3.1.0) */ @OpenAPI31 public void setBooleanSchemaValue(Boolean booleanSchemaValue) { this.booleanSchemaValue = booleanSchemaValue; } /** * * @since 2.2.2 (OpenAPI 3.1.0) */ @OpenAPI31 public Schema booleanSchemaValue(Boolean booleanSchemaValue) { this.booleanSchemaValue = booleanSchemaValue; return this; } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/StringSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.List; import java.util.Objects; /** * StringSchema */ public class StringSchema extends Schema { public StringSchema() { super("string", null); } @Override public StringSchema type(String type) { super.setType(type); return this; } public StringSchema _default(String _default) { super.setDefault(_default); return this; } public StringSchema _enum(List _enum) { super.setEnum(_enum); return this; } public StringSchema addEnumItem(String _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override protected String cast(Object value) { if (value != null) { try { return value.toString(); } catch (Exception e) { } } return null; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class StringSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/UUIDSchema.java ================================================ package io.swagger.v3.oas.models.media; import java.util.List; import java.util.Objects; import java.util.UUID; /** * UUIDSchema */ public class UUIDSchema extends Schema { public UUIDSchema() { super("string", "uuid"); } @Override public UUIDSchema type(String type) { super.setType(type); return this; } @Override public UUIDSchema format(String format) { super.setFormat(format); return this; } public UUIDSchema _default(UUID _default) { super.setDefault(_default); return this; } public UUIDSchema _default(String _default) { if (_default != null) { super.setDefault(UUID.fromString(_default)); } return this; } public UUIDSchema _enum(List _enum) { super.setEnum(_enum); return this; } public UUIDSchema addEnumItem(UUID _enumItem) { super.addEnumItemObject(_enumItem); return this; } @Override protected UUID cast(Object value) { if (value != null) { try { return UUID.fromString(value.toString()); } catch (Exception e) { } } return null; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class UUIDSchema {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/media/XML.java ================================================ package io.swagger.v3.oas.models.media; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.Objects; /** * XML * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#xml-object" */ public class XML { private String name = null; private String namespace = null; private String prefix = null; private Boolean attribute = null; private Boolean wrapped = null; private java.util.Map extensions = null; /** * returns the name property from a XML instance. * * @return String name **/ public String getName() { return name; } public void setName(String name) { this.name = name; } public XML name(String name) { this.name = name; return this; } /** * returns the namespace property from a XML instance. * * @return String namespace **/ public String getNamespace() { return namespace; } public void setNamespace(String namespace) { this.namespace = namespace; } public XML namespace(String namespace) { this.namespace = namespace; return this; } /** * returns the prefix property from a XML instance. * * @return String prefix **/ public String getPrefix() { return prefix; } public void setPrefix(String prefix) { this.prefix = prefix; } public XML prefix(String prefix) { this.prefix = prefix; return this; } /** * returns the attribute property from a XML instance. * * @return Boolean attribute **/ public Boolean getAttribute() { return attribute; } public void setAttribute(Boolean attribute) { this.attribute = attribute; } public XML attribute(Boolean attribute) { this.attribute = attribute; return this; } /** * returns the wrapped property from a XML instance. * * @return Boolean wrapped **/ public Boolean getWrapped() { return wrapped; } public void setWrapped(Boolean wrapped) { this.wrapped = wrapped; } public XML wrapped(Boolean wrapped) { this.wrapped = wrapped; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } XML XML = (XML) o; return Objects.equals(this.name, XML.name) && Objects.equals(this.namespace, XML.namespace) && Objects.equals(this.prefix, XML.prefix) && Objects.equals(this.attribute, XML.attribute) && Objects.equals(this.wrapped, XML.wrapped) && Objects.equals(this.extensions, XML.extensions); } @Override public int hashCode() { return Objects.hash(name, namespace, prefix, attribute, wrapped, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public XML extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class XML {\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" namespace: ").append(toIndentedString(namespace)).append("\n"); sb.append(" prefix: ").append(toIndentedString(prefix)).append("\n"); sb.append(" attribute: ").append(toIndentedString(attribute)).append("\n"); sb.append(" wrapped: ").append(toIndentedString(wrapped)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/parameters/CookieParameter.java ================================================ package io.swagger.v3.oas.models.parameters; import java.util.Objects; /** * CookieParameter */ public class CookieParameter extends Parameter { private String in = "cookie"; /** * returns the in property from a CookieParameter instance. * * @return String in **/ @Override public String getIn() { return in; } @Override public void setIn(String in) { this.in = in; } @Override public CookieParameter in(String in) { this.in = in; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } CookieParameter cookieParameter = (CookieParameter) o; return Objects.equals(this.in, cookieParameter.in) && super.equals(o); } @Override public int hashCode() { return Objects.hash(in, super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class CookieParameter {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append(" in: ").append(toIndentedString(in)).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/parameters/HeaderParameter.java ================================================ package io.swagger.v3.oas.models.parameters; import java.util.Objects; /** * HeaderParameter */ public class HeaderParameter extends Parameter { private String in = "header"; /** * returns the in property from a HeaderParameter instance. * * @return String in **/ @Override public String getIn() { return in; } @Override public void setIn(String in) { this.in = in; } @Override public HeaderParameter in(String in) { this.in = in; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } HeaderParameter headerParameter = (HeaderParameter) o; return Objects.equals(this.in, headerParameter.in) && super.equals(o); } @Override public int hashCode() { return Objects.hash(in, super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class HeaderParameter {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append(" in: ").append(toIndentedString(in)).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/parameters/Parameter.java ================================================ package io.swagger.v3.oas.models.parameters; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.Schema; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * Parameter * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#parameter-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#parameter-object" */ public class Parameter { private String name = null; private String in = null; private String description = null; private Boolean required = null; private Boolean deprecated = null; private Boolean allowEmptyValue = null; private String $ref = null; /** * Gets or Sets style */ public enum StyleEnum { MATRIX("matrix"), LABEL("label"), FORM("form"), SIMPLE("simple"), SPACEDELIMITED("spaceDelimited"), PIPEDELIMITED("pipeDelimited"), DEEPOBJECT("deepObject"); private String value; StyleEnum(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } private StyleEnum style = null; private Boolean explode = null; private Boolean allowReserved = null; private Schema schema = null; private Map examples = null; private Object example = null; private Content content = null; private java.util.Map extensions = null; /** * returns the name property from a Parameter instance. * * @return String name **/ public String getName() { return name; } public void setName(String name) { this.name = name; } public Parameter name(String name) { this.name = name; return this; } /** * returns the in property from a Parameter instance. * * @return String in **/ public String getIn() { return in; } public void setIn(String in) { if ("path".equals(in)) { this.required = true; } this.in = in; } public Parameter in(String in) { setIn(in); return this; } /** * returns the description property from a Parameter instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Parameter description(String description) { this.description = description; return this; } /** * returns the required property from a Parameter instance. * * @return Boolean required **/ public Boolean getRequired() { return required; } public void setRequired(Boolean required) { this.required = required; } public Parameter required(Boolean required) { this.required = required; return this; } /** * returns the deprecated property from a Parameter instance. * * @return Boolean deprecated **/ public Boolean getDeprecated() { return deprecated; } public void setDeprecated(Boolean deprecated) { this.deprecated = deprecated; } public Parameter deprecated(Boolean deprecated) { this.deprecated = deprecated; return this; } /** * returns the allowEmptyValue property from a Parameter instance. * * @return Boolean allowEmptyValue **/ public Boolean getAllowEmptyValue() { return allowEmptyValue; } public void setAllowEmptyValue(Boolean allowEmptyValue) { this.allowEmptyValue = allowEmptyValue; } public Parameter allowEmptyValue(Boolean allowEmptyValue) { this.allowEmptyValue = allowEmptyValue; return this; } /** * returns the style property from a Parameter instance. * * @return StyleEnum style **/ public StyleEnum getStyle() { return style; } public void setStyle(StyleEnum style) { this.style = style; } public Parameter style(StyleEnum style) { this.style = style; return this; } /** * returns the explode property from a Parameter instance. * * @return Boolean explode **/ public Boolean getExplode() { return explode; } public void setExplode(Boolean explode) { this.explode = explode; } public Parameter explode(Boolean explode) { this.explode = explode; return this; } /** * returns the allowReserved property from a Parameter instance. * * @return Boolean allowReserved **/ public Boolean getAllowReserved() { return allowReserved; } public void setAllowReserved(Boolean allowReserved) { this.allowReserved = allowReserved; } public Parameter allowReserved(Boolean allowReserved) { this.allowReserved = allowReserved; return this; } /** * returns the schema property from a Parameter instance. * * @return Schema schema **/ public Schema getSchema() { return schema; } public void setSchema(Schema schema) { this.schema = schema; } public Parameter schema(Schema schema) { this.schema = schema; return this; } /** * returns the examples property from a Parameter instance. * * @return Map<String, Example> examples **/ public Map getExamples() { return examples; } public void setExamples(Map examples) { this.examples = examples; } public Parameter examples(Map examples) { this.examples = examples; return this; } public Parameter addExample(String key, Example examplesItem) { if (this.examples == null) { this.examples = new LinkedHashMap<>(); } this.examples.put(key, examplesItem); return this; } /** * returns the example property from a Parameter instance. * * @return String example **/ public Object getExample() { return example; } public void setExample(Object example) { this.example = example; } public Parameter example(Object example) { this.example = example; return this; } /** * returns the content property from a Parameter instance. * * @return Content content **/ public Content getContent() { return content; } public void setContent(Content content) { this.content = content; } public Parameter content(Content content) { this.content = content; return this; } public String get$ref() { return $ref; } public void set$ref(String $ref) { if ($ref != null && !$ref.startsWith("#/components/parameters/") && $ref.indexOf('.') == -1 && $ref.indexOf('/') == -1) { $ref = "#/components/parameters/" + $ref; } this.$ref = $ref; } public Parameter $ref(String $ref) { set$ref($ref); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Parameter parameter = (Parameter) o; return Objects.equals(this.name, parameter.name) && Objects.equals(this.in, parameter.in) && Objects.equals(this.description, parameter.description) && Objects.equals(this.required, parameter.required) && Objects.equals(this.deprecated, parameter.deprecated) && Objects.equals(this.allowEmptyValue, parameter.allowEmptyValue) && Objects.equals(this.style, parameter.style) && Objects.equals(this.explode, parameter.explode) && Objects.equals(this.allowReserved, parameter.allowReserved) && Objects.equals(this.schema, parameter.schema) && Objects.equals(this.examples, parameter.examples) && Objects.equals(this.example, parameter.example) && Objects.equals(this.content, parameter.content) && Objects.equals(this.$ref, parameter.$ref) && Objects.equals(this.extensions, parameter.extensions); } @Override public int hashCode() { return Objects.hash(name, in, description, required, deprecated, allowEmptyValue, style, explode, allowReserved, schema, examples, example, content, $ref, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Parameter extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Parameter {\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" in: ").append(toIndentedString(in)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" required: ").append(toIndentedString(required)).append("\n"); sb.append(" deprecated: ").append(toIndentedString(deprecated)).append("\n"); sb.append(" allowEmptyValue: ").append(toIndentedString(allowEmptyValue)).append("\n"); sb.append(" style: ").append(toIndentedString(style)).append("\n"); sb.append(" explode: ").append(toIndentedString(explode)).append("\n"); sb.append(" allowReserved: ").append(toIndentedString(allowReserved)).append("\n"); sb.append(" schema: ").append(toIndentedString(schema)).append("\n"); sb.append(" examples: ").append(toIndentedString(examples)).append("\n"); sb.append(" example: ").append(toIndentedString(example)).append("\n"); sb.append(" content: ").append(toIndentedString(content)).append("\n"); sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ static String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/parameters/PathParameter.java ================================================ package io.swagger.v3.oas.models.parameters; import java.util.Objects; /** * PathParameter */ public class PathParameter extends Parameter { private String in = "path"; private Boolean required = true; /** * returns the in property from a PathParameter instance. * * @return String in **/ @Override public String getIn() { return in; } @Override public void setIn(String in) { this.in = in; } @Override public PathParameter in(String in) { this.in = in; return this; } /** * returns the required property from a PathParameter instance. * * @return Boolean required **/ @Override public Boolean getRequired() { return required; } @Override public void setRequired(Boolean required) { this.required = required; } @Override public PathParameter required(Boolean required) { this.required = required; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } PathParameter pathParameter = (PathParameter) o; return Objects.equals(this.in, pathParameter.in) && Objects.equals(this.required, pathParameter.required) && super.equals(o); } @Override public int hashCode() { return Objects.hash(in, required, super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class PathParameter {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append(" in: ").append(toIndentedString(in)).append("\n"); sb.append(" required: ").append(toIndentedString(required)).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/parameters/QueryParameter.java ================================================ package io.swagger.v3.oas.models.parameters; import java.util.Objects; /** * QueryParameter */ public class QueryParameter extends Parameter { private String in = "query"; /** * returns the in property from a QueryParameter instance. * * @return String in **/ @Override public String getIn() { return in; } @Override public void setIn(String in) { this.in = in; } @Override public QueryParameter in(String in) { this.in = in; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } QueryParameter queryParameter = (QueryParameter) o; return Objects.equals(this.in, queryParameter.in) && super.equals(o); } @Override public int hashCode() { return Objects.hash(in, super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class QueryParameter {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append(" in: ").append(toIndentedString(in)).append("\n"); sb.append("}"); return sb.toString(); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/parameters/RequestBody.java ================================================ package io.swagger.v3.oas.models.parameters; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.media.Content; /** * RequestBody * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#requestBody-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#request-body-object" */ public class RequestBody { private String description = null; private Content content = null; private Boolean required = null; private java.util.Map extensions = null; private String $ref = null; /** * returns the description property from a RequestBody instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public RequestBody description(String description) { this.description = description; return this; } /** * returns the content property from a RequestBody instance. * * @return Content content **/ public Content getContent() { return content; } public void setContent(Content content) { this.content = content; } public RequestBody content(Content content) { this.content = content; return this; } /** * returns the required property from a RequestBody instance. * * @return Boolean required **/ public Boolean getRequired() { return required; } public void setRequired(Boolean required) { this.required = required; } public RequestBody required(Boolean required) { this.required = required; return this; } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public RequestBody extensions(java.util.Map extensions) { this.extensions = extensions; return this; } public String get$ref() { return $ref; } public void set$ref(String $ref) { if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { $ref = "#/components/requestBodies/" + $ref; } this.$ref = $ref; } public RequestBody $ref(String $ref) { set$ref($ref); return this; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof RequestBody)) { return false; } RequestBody that = (RequestBody) o; if (description != null ? !description.equals(that.description) : that.description != null) { return false; } if (content != null ? !content.equals(that.content) : that.content != null) { return false; } if (required != null ? !required.equals(that.required) : that.required != null) { return false; } if (extensions != null ? !extensions.equals(that.extensions) : that.extensions != null) { return false; } return $ref != null ? $ref.equals(that.$ref) : that.$ref == null; } @Override public int hashCode() { int result = description != null ? description.hashCode() : 0; result = 31 * result + (content != null ? content.hashCode() : 0); result = 31 * result + (required != null ? required.hashCode() : 0); result = 31 * result + (extensions != null ? extensions.hashCode() : 0); result = 31 * result + ($ref != null ? $ref.hashCode() : 0); return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class RequestBody {\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" content: ").append(toIndentedString(content)).append("\n"); sb.append(" required: ").append(toIndentedString(required)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/responses/ApiResponse.java ================================================ package io.swagger.v3.oas.models.responses; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.media.Content; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * ApiResponse * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#response-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#response-object" */ public class ApiResponse { private String description = null; private Map headers = null; private Content content = null; private java.util.Map links = null; private java.util.Map extensions = null; private String $ref = null; /** * returns the description property from a ApiResponse instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public ApiResponse description(String description) { this.description = description; return this; } /** * returns the headers property from a ApiResponse instance. * * @return headers **/ public Map getHeaders() { return headers; } public void setHeaders(Map headers) { this.headers = headers; } public ApiResponse headers(Map headers) { this.headers = headers; return this; } public ApiResponse addHeaderObject(String name, Header header) { if (this.headers == null) { headers = new LinkedHashMap<>(); } headers.put(name, header); return this; } /** * returns the content property from a ApiResponse instance. * * @return Content content **/ public Content getContent() { return content; } public void setContent(Content content) { this.content = content; } public ApiResponse content(Content content) { this.content = content; return this; } /** * returns the links property from a ApiResponse instance. * * @return Link links **/ public Map getLinks() { return links; } public void setLinks(Map links) { this.links = links; } public ApiResponse links(Map links) { this.links = links; return this; } public ApiResponse addLink(String name, Link link) { if (this.links == null) { this.links = new LinkedHashMap<>(); } this.links.put(name, link); return this; } public ApiResponse link(String name, Link link) { return this.addLink(name, link); } /** * returns the $ref property from an ApiResponse instance. * * @return String $ref **/ public String get$ref() { return $ref; } public void set$ref(String $ref) { if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { $ref = "#/components/responses/" + $ref; } this.$ref = $ref; } public ApiResponse $ref(String $ref) { set$ref($ref); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ApiResponse apiResponse = (ApiResponse) o; return Objects.equals(this.description, apiResponse.description) && Objects.equals(this.headers, apiResponse.headers) && Objects.equals(this.content, apiResponse.content) && Objects.equals(this.links, apiResponse.links) && Objects.equals(this.extensions, apiResponse.extensions) && Objects.equals(this.$ref, apiResponse.$ref); } @Override public int hashCode() { return Objects.hash(description, headers, content, links, extensions, $ref); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public ApiResponse extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ApiResponse {\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" headers: ").append(toIndentedString(headers)).append("\n"); sb.append(" content: ").append(toIndentedString(content)).append("\n"); sb.append(" links: ").append(toIndentedString(links)).append("\n"); sb.append(" extensions: ").append(toIndentedString(extensions)).append("\n"); sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/responses/ApiResponses.java ================================================ package io.swagger.v3.oas.models.responses; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.LinkedHashMap; import java.util.Objects; /** * ApiResponses * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#responses-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#responses-object" */ public class ApiResponses extends LinkedHashMap { public static final String DEFAULT = "default"; private java.util.Map extensions = null; public ApiResponses addApiResponse(String name, ApiResponse item) { this.put(name, item); return this; } /** * returns the default property from a ApiResponses instance. * * @return ApiResponse _default **/ @Deprecated public ApiResponse getDefault() { return this.get(DEFAULT); } @Deprecated public void setDefault(ApiResponse _default) { addApiResponse(DEFAULT, _default); } @Deprecated public ApiResponses _default(ApiResponse _default) { setDefault(_default); return this; } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public ApiResponses extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } if (!super.equals(o)) { return false; } ApiResponses apiResponses = (ApiResponses) o; return Objects.equals(this.extensions, apiResponses.extensions); } @Override public int hashCode() { return Objects.hash(super.hashCode(), extensions); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ApiResponses {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append(" extensions: ").append(toIndentedString(extensions)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/security/OAuthFlow.java ================================================ package io.swagger.v3.oas.models.security; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.Objects; /** * OAuthFlow * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#oauth-flows-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#oauth-flows-object" */ public class OAuthFlow { private String authorizationUrl = null; private String tokenUrl = null; private String refreshUrl = null; private Scopes scopes = null; private java.util.Map extensions = null; /** * returns the authorizationUrl property from a OAuthFlow instance. * * @return String authorizationUrl **/ public String getAuthorizationUrl() { return authorizationUrl; } public void setAuthorizationUrl(String authorizationUrl) { this.authorizationUrl = authorizationUrl; } public OAuthFlow authorizationUrl(String authorizationUrl) { this.authorizationUrl = authorizationUrl; return this; } /** * returns the tokenUrl property from a OAuthFlow instance. * * @return String tokenUrl **/ public String getTokenUrl() { return tokenUrl; } public void setTokenUrl(String tokenUrl) { this.tokenUrl = tokenUrl; } public OAuthFlow tokenUrl(String tokenUrl) { this.tokenUrl = tokenUrl; return this; } /** * returns the refreshUrl property from a OAuthFlow instance. * * @return String refreshUrl **/ public String getRefreshUrl() { return refreshUrl; } public void setRefreshUrl(String refreshUrl) { this.refreshUrl = refreshUrl; } public OAuthFlow refreshUrl(String refreshUrl) { this.refreshUrl = refreshUrl; return this; } /** * returns the scopes property from a OAuthFlow instance. * * @return Scopes scopes **/ public Scopes getScopes() { return scopes; } public void setScopes(Scopes scopes) { this.scopes = scopes; } public OAuthFlow scopes(Scopes scopes) { this.scopes = scopes; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } OAuthFlow oauthFlow = (OAuthFlow) o; return Objects.equals(this.authorizationUrl, oauthFlow.authorizationUrl) && Objects.equals(this.tokenUrl, oauthFlow.tokenUrl) && Objects.equals(this.refreshUrl, oauthFlow.refreshUrl) && Objects.equals(this.scopes, oauthFlow.scopes) && Objects.equals(this.extensions, oauthFlow.extensions); } @Override public int hashCode() { return Objects.hash(authorizationUrl, tokenUrl, refreshUrl, scopes, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public OAuthFlow extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class OAuthFlow {\n"); sb.append(" authorizationUrl: ").append(toIndentedString(authorizationUrl)).append("\n"); sb.append(" tokenUrl: ").append(toIndentedString(tokenUrl)).append("\n"); sb.append(" refreshUrl: ").append(toIndentedString(refreshUrl)).append("\n"); sb.append(" scopes: ").append(toIndentedString(scopes)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/security/OAuthFlows.java ================================================ package io.swagger.v3.oas.models.security; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.Objects; /** * OAuthFlows * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#oauth-flows-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#oauth-flows-object" */ public class OAuthFlows { private OAuthFlow implicit = null; private OAuthFlow password = null; private OAuthFlow clientCredentials = null; private OAuthFlow authorizationCode = null; private java.util.Map extensions = null; /** * returns the implicit property from a OAuthFlows instance. * * @return OAuthFlow implicit **/ public OAuthFlow getImplicit() { return implicit; } public void setImplicit(OAuthFlow implicit) { this.implicit = implicit; } public OAuthFlows implicit(OAuthFlow implicit) { this.implicit = implicit; return this; } /** * returns the password property from a OAuthFlows instance. * * @return OAuthFlow password **/ public OAuthFlow getPassword() { return password; } public void setPassword(OAuthFlow password) { this.password = password; } public OAuthFlows password(OAuthFlow password) { this.password = password; return this; } /** * returns the clientCredentials property from a OAuthFlows instance. * * @return OAuthFlow clientCredentials **/ public OAuthFlow getClientCredentials() { return clientCredentials; } public void setClientCredentials(OAuthFlow clientCredentials) { this.clientCredentials = clientCredentials; } public OAuthFlows clientCredentials(OAuthFlow clientCredentials) { this.clientCredentials = clientCredentials; return this; } /** * returns the authorizationCode property from a OAuthFlows instance. * * @return OAuthFlow authorizationCode **/ public OAuthFlow getAuthorizationCode() { return authorizationCode; } public void setAuthorizationCode(OAuthFlow authorizationCode) { this.authorizationCode = authorizationCode; } public OAuthFlows authorizationCode(OAuthFlow authorizationCode) { this.authorizationCode = authorizationCode; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } OAuthFlows oauthFlows = (OAuthFlows) o; return Objects.equals(this.implicit, oauthFlows.implicit) && Objects.equals(this.password, oauthFlows.password) && Objects.equals(this.clientCredentials, oauthFlows.clientCredentials) && Objects.equals(this.authorizationCode, oauthFlows.authorizationCode) && Objects.equals(this.extensions, oauthFlows.extensions); } @Override public int hashCode() { return Objects.hash(implicit, password, clientCredentials, authorizationCode, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public OAuthFlows extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class OAuthFlows {\n"); sb.append(" implicit: ").append(toIndentedString(implicit)).append("\n"); sb.append(" password: ").append(toIndentedString(password)).append("\n"); sb.append(" clientCredentials: ").append(toIndentedString(clientCredentials)).append("\n"); sb.append(" authorizationCode: ").append(toIndentedString(authorizationCode)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/security/Scopes.java ================================================ package io.swagger.v3.oas.models.security; import java.util.LinkedHashMap; import java.util.Objects; /** * Scopes * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#scoped-object" */ public class Scopes extends LinkedHashMap { public Scopes() { } private java.util.Map extensions = null; public Scopes addString(String name, String item) { this.put(name, item); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Scopes scopes = (Scopes) o; return Objects.equals(this.extensions, scopes.extensions) && super.equals(o); } @Override public int hashCode() { return Objects.hash(extensions, super.hashCode()); } /** * @deprecated As extensions don't make sense at this level */ @Deprecated public java.util.Map getExtensions() { return extensions; } /** * @deprecated As extensions don't make sense at this level */ @Deprecated public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } /** * @deprecated As extensions don't make sense at this level */ @Deprecated public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } /** * @deprecated As extensions don't make sense at this level */ @Deprecated public Scopes extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Scopes {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/security/SecurityRequirement.java ================================================ package io.swagger.v3.oas.models.security; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; /** * SecurityRequirement * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#security-requirement-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#security-requirement-object" */ public class SecurityRequirement extends LinkedHashMap> { public SecurityRequirement() { } public SecurityRequirement addList(String name, String item) { this.put(name, Arrays.asList(item)); return this; } public SecurityRequirement addList(String name, List item) { this.put(name, item); return this; } public SecurityRequirement addList(String name) { this.put(name, new ArrayList<>()); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } return super.equals(o); } @Override public int hashCode() { return Objects.hash(super.hashCode()); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class SecurityRequirement {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/security/SecurityScheme.java ================================================ package io.swagger.v3.oas.models.security; import io.swagger.v3.oas.models.annotations.OpenAPI31; /** * SecurityScheme * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#security-scheme-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#security-scheme-object" */ public class SecurityScheme { /** * Gets or Sets type */ public enum Type { APIKEY("apiKey"), HTTP("http"), OAUTH2("oauth2"), OPENIDCONNECT("openIdConnect"), MUTUALTLS("mutualTLS"); private String value; Type(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } private Type type = null; private String description = null; private String name = null; private String $ref = null; /** * Gets or Sets in */ public enum In { COOKIE("cookie"), HEADER("header"), QUERY("query"); private String value; In(String value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } private In in = null; private String scheme = null; private String bearerFormat = null; private OAuthFlows flows = null; private String openIdConnectUrl = null; private java.util.Map extensions = null; /** * returns the type property from a SecurityScheme instance. * * @return Type type **/ public Type getType() { return type; } public void setType(Type type) { this.type = type; } public SecurityScheme type(Type type) { this.type = type; return this; } /** * returns the description property from a SecurityScheme instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public SecurityScheme description(String description) { this.description = description; return this; } /** * returns the name property from a SecurityScheme instance. * * @return String name **/ public String getName() { return name; } public void setName(String name) { this.name = name; } public SecurityScheme name(String name) { this.name = name; return this; } /** * returns the in property from a SecurityScheme instance. * * @return In in **/ public In getIn() { return in; } public void setIn(In in) { this.in = in; } public SecurityScheme in(In in) { this.in = in; return this; } /** * returns the scheme property from a SecurityScheme instance. * * @return String scheme **/ public String getScheme() { return scheme; } public void setScheme(String scheme) { this.scheme = scheme; } public SecurityScheme scheme(String scheme) { this.scheme = scheme; return this; } /** * returns the bearerFormat property from a SecurityScheme instance. * * @return String bearerFormat **/ public String getBearerFormat() { return bearerFormat; } public void setBearerFormat(String bearerFormat) { this.bearerFormat = bearerFormat; } public SecurityScheme bearerFormat(String bearerFormat) { this.bearerFormat = bearerFormat; return this; } /** * returns the flows property from a SecurityScheme instance. * * @return OAuthFlows flows **/ public OAuthFlows getFlows() { return flows; } public void setFlows(OAuthFlows flows) { this.flows = flows; } public SecurityScheme flows(OAuthFlows flows) { this.flows = flows; return this; } /** * returns the openIdConnectUrl property from a SecurityScheme instance. * * @return String openIdConnectUrl **/ public String getOpenIdConnectUrl() { return openIdConnectUrl; } public void setOpenIdConnectUrl(String openIdConnectUrl) { this.openIdConnectUrl = openIdConnectUrl; } public SecurityScheme openIdConnectUrl(String openIdConnectUrl) { this.openIdConnectUrl = openIdConnectUrl; return this; } public java.util.Map getExtensions() { return extensions; } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public SecurityScheme extensions(java.util.Map extensions) { this.extensions = extensions; return this; } /** * returns the $ref property from an SecurityScheme instance. * * @return String $ref **/ public String get$ref() { return $ref; } public void set$ref(String $ref) { if ($ref != null && ($ref.indexOf('.') == -1 && $ref.indexOf('/') == -1)) { $ref = "#/components/securitySchemes/" + $ref; } this.$ref = $ref; } public SecurityScheme $ref(String $ref) { set$ref($ref); return this; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof SecurityScheme)) { return false; } SecurityScheme that = (SecurityScheme) o; if (type != that.type) { return false; } if (description != null ? !description.equals(that.description) : that.description != null) { return false; } if (name != null ? !name.equals(that.name) : that.name != null) { return false; } if ($ref != null ? !$ref.equals(that.$ref) : that.$ref != null) { return false; } if (in != that.in) { return false; } if (scheme != null ? !scheme.equals(that.scheme) : that.scheme != null) { return false; } if (bearerFormat != null ? !bearerFormat.equals(that.bearerFormat) : that.bearerFormat != null) { return false; } if (flows != null ? !flows.equals(that.flows) : that.flows != null) { return false; } if (openIdConnectUrl != null ? !openIdConnectUrl.equals(that.openIdConnectUrl) : that.openIdConnectUrl != null) { return false; } return extensions != null ? extensions.equals(that.extensions) : that.extensions == null; } @Override public int hashCode() { int result = type != null ? type.hashCode() : 0; result = 31 * result + (description != null ? description.hashCode() : 0); result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + ($ref != null ? $ref.hashCode() : 0); result = 31 * result + (in != null ? in.hashCode() : 0); result = 31 * result + (scheme != null ? scheme.hashCode() : 0); result = 31 * result + (bearerFormat != null ? bearerFormat.hashCode() : 0); result = 31 * result + (flows != null ? flows.hashCode() : 0); result = 31 * result + (openIdConnectUrl != null ? openIdConnectUrl.hashCode() : 0); result = 31 * result + (extensions != null ? extensions.hashCode() : 0); return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class SecurityScheme {\n"); sb.append(" type: ").append(toIndentedString(type)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" in: ").append(toIndentedString(in)).append("\n"); sb.append(" scheme: ").append(toIndentedString(scheme)).append("\n"); sb.append(" bearerFormat: ").append(toIndentedString(bearerFormat)).append("\n"); sb.append(" flows: ").append(toIndentedString(flows)).append("\n"); sb.append(" openIdConnectUrl: ").append(toIndentedString(openIdConnectUrl)).append("\n"); sb.append(" $ref: ").append(toIndentedString($ref)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/servers/Server.java ================================================ package io.swagger.v3.oas.models.servers; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.Objects; /** * Server * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#server-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#server-object" */ public class Server { private String url = null; private String description = null; private ServerVariables variables = null; private java.util.Map extensions = null; /** * returns the url property from a Server instance. * * @return String url **/ public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Server url(String url) { this.url = url; return this; } /** * returns the description property from a Server instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Server description(String description) { this.description = description; return this; } /** * returns the variables property from a Server instance. * * @return ServerVariables variables **/ public ServerVariables getVariables() { return variables; } public void setVariables(ServerVariables variables) { this.variables = variables; } public Server variables(ServerVariables variables) { this.variables = variables; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Server server = (Server) o; return Objects.equals(this.url, server.url) && Objects.equals(this.description, server.description) && Objects.equals(this.variables, server.variables) && Objects.equals(this.extensions, server.extensions); } @Override public int hashCode() { return Objects.hash(url, description, variables, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Server extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Server {\n"); sb.append(" url: ").append(toIndentedString(url)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" variables: ").append(toIndentedString(variables)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/servers/ServerVariable.java ================================================ package io.swagger.v3.oas.models.servers; import io.swagger.v3.oas.models.annotations.OpenAPI31; import java.util.ArrayList; import java.util.List; import java.util.Objects; /** * ServerVariable * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#server-variable-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#server-variable-object" */ public class ServerVariable { private List _enum = null; private String _default = null; private String description = null; private java.util.Map extensions = null; /** * returns the _enum property from a ServerVariable instance. * * @return List<String> _enum **/ public List getEnum() { return _enum; } public void setEnum(List _enum) { this._enum = _enum; } public ServerVariable _enum(List _enum) { this._enum = _enum; return this; } public ServerVariable addEnumItem(String _enumItem) { if (this._enum == null) { this._enum = new ArrayList<>(); } this._enum.add(_enumItem); return this; } /** * returns the _default property from a ServerVariable instance. * * @return String _default **/ public String getDefault() { return _default; } public void setDefault(String _default) { this._default = _default; } public ServerVariable _default(String _default) { this._default = _default; return this; } /** * returns the description property from a ServerVariable instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public ServerVariable description(String description) { this.description = description; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ServerVariable serverVariable = (ServerVariable) o; return Objects.equals(this._enum, serverVariable._enum) && Objects.equals(this._default, serverVariable._default) && Objects.equals(this.description, serverVariable.description) && Objects.equals(this.extensions, serverVariable.extensions); } @Override public int hashCode() { return Objects.hash(_enum, _default, description, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public ServerVariable extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ServerVariable {\n"); sb.append(" _enum: ").append(toIndentedString(_enum)).append("\n"); sb.append(" _default: ").append(toIndentedString(_default)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/servers/ServerVariables.java ================================================ package io.swagger.v3.oas.models.servers; import java.util.LinkedHashMap; import java.util.Objects; /** * ServerVariables * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#server-variables-object" */ public class ServerVariables extends LinkedHashMap { public ServerVariables() { } private java.util.Map extensions = null; public ServerVariables addServerVariable(String name, ServerVariable item) { this.put(name, item); return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ServerVariables serverVariables = (ServerVariables) o; return Objects.equals(this.extensions, serverVariables.extensions) && super.equals(o); } @Override public int hashCode() { return Objects.hash(extensions, super.hashCode()); } /** * @deprecated As extensions don't make sense at this level */ @Deprecated public java.util.Map getExtensions() { return extensions; } /** * @deprecated As extensions don't make sense at this level */ @Deprecated public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } /** * @deprecated As extensions don't make sense at this level */ @Deprecated public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } /** * @deprecated As extensions don't make sense at this level */ @Deprecated public ServerVariables extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ServerVariables {\n"); sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/main/java/io/swagger/v3/oas/models/tags/Tag.java ================================================ package io.swagger.v3.oas.models.tags; import io.swagger.v3.oas.models.annotations.OpenAPI31; import io.swagger.v3.oas.models.ExternalDocumentation; import java.util.Objects; /** * Tag * * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.0.4/versions/3.0.4.md#tag-object" * @see "https://github.com/OAI/OpenAPI-Specification/blob/3.1.1/versions/3.1.1.md#tag-object" */ public class Tag { private String name = null; private String description = null; private ExternalDocumentation externalDocs = null; private java.util.Map extensions = null; /** * returns the name property from a Tag instance. * * @return String name **/ public String getName() { return name; } public void setName(String name) { this.name = name; } public Tag name(String name) { this.name = name; return this; } /** * returns the description property from a Tag instance. * * @return String description **/ public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Tag description(String description) { this.description = description; return this; } /** * returns the externalDocs property from a Tag instance. * * @return ExternalDocumentation externalDocs **/ public ExternalDocumentation getExternalDocs() { return externalDocs; } public void setExternalDocs(ExternalDocumentation externalDocs) { this.externalDocs = externalDocs; } public Tag externalDocs(ExternalDocumentation externalDocs) { this.externalDocs = externalDocs; return this; } @Override public boolean equals(java.lang.Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Tag tag = (Tag) o; return Objects.equals(this.name, tag.name) && Objects.equals(this.description, tag.description) && Objects.equals(this.externalDocs, tag.externalDocs) && Objects.equals(this.extensions, tag.extensions); } @Override public int hashCode() { return Objects.hash(name, description, externalDocs, extensions); } public java.util.Map getExtensions() { return extensions; } public void addExtension(String name, Object value) { if (name == null || name.isEmpty() || !name.startsWith("x-")) { return; } if (this.extensions == null) { this.extensions = new java.util.LinkedHashMap<>(); } this.extensions.put(name, value); } @OpenAPI31 public void addExtension31(String name, Object value) { if (name != null && (name.startsWith("x-oas-") || name.startsWith("x-oai-"))) { return; } addExtension(name, value); } public void setExtensions(java.util.Map extensions) { this.extensions = extensions; } public Tag extensions(java.util.Map extensions) { this.extensions = extensions; return this; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Tag {\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" externalDocs: ").append(toIndentedString(externalDocs)).append("\n"); sb.append("}"); return sb.toString(); } /** * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ private String toIndentedString(java.lang.Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } } ================================================ FILE: modules/swagger-models/src/test/java/io/swagger/test/SchemaTests.java ================================================ package io.swagger.test; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import org.testng.annotations.Test; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; import static org.testng.Assert.fail; public class SchemaTests { @Test public void AdditionalPropertiesBoolean(){ Map schemas = new HashMap<>(); schemas.put("StringSchema", new StringSchema() .description("simple string schema") .minLength(3) .maxLength(100) .example("it works") .additionalProperties(true) ); } @Test public void AdditionalPropertiesSchema(){ Map schemas = new HashMap<>(); schemas.put("IntegerSchema", new IntegerSchema() .description("simple integer schema") .multipleOf(new BigDecimal(3)) .minimum(new BigDecimal(6)) .additionalProperties(new StringSchema()) ); } @Test public void AdditionalPropertiesException()throws Exception{ Map schemas = new HashMap<>(); try { schemas.put("IntegerSchema", new IntegerSchema() .description("simple integer schema") .multipleOf(new BigDecimal(3)) .minimum(new BigDecimal(6)) .additionalProperties("ok") ); fail("Should have thrown an exception"); }catch (Exception exception){ } } } ================================================ FILE: modules/swagger-models/src/test/java/io/swagger/test/SimpleBuilderTest.java ================================================ package io.swagger.test; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.ExternalDocumentation; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.links.Link; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.QueryParameter; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.tags.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class SimpleBuilderTest { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleBuilderTest.class); @Test public void testBuilder() throws Exception { // basic metadata OpenAPI oai = new OpenAPI() .info(new Info() .contact(new Contact() .email("tony@eatbacon.org") .name("Tony the Tam") .url("https://foo.bar"))) .externalDocs(new ExternalDocumentation() .description("read more here") .url("http://swagger.io")) .addTagsItem(new Tag() .name("funky dunky") .description("all about neat things")) .extensions(new HashMap() {{ put("x-fancy-extension", "something"); }}); Map schemas = new HashMap<>(); schemas .put("StringSchema", new StringSchema() .description("simple string schema") .minLength(3) .maxLength(100) .example("it works") ); schemas.put("IntegerSchema", new IntegerSchema() .description("simple integer schema") .multipleOf(new BigDecimal(3)) .minimum(new BigDecimal(6)) ); oai.components(new Components() .schemas(schemas)); schemas.put("Address", new Schema() .description("address object") .addProperties("street", new StringSchema() .description("the street number")) .addProperties("city", new StringSchema() .description("city")) .addProperties("state", new StringSchema() .description("state") .minLength(2) .maxLength(2)) .addProperties("zip", new StringSchema() .description("zip code") .pattern("^\\d{5}(?:[-\\s]\\d{4})?$") .minLength(2) .maxLength(2)) .addProperties("country", new StringSchema() ._enum(new ArrayList() {{ this.add("US"); }})) .description("2-digit country code") .minLength(2) .maxLength(2) ); oai.paths(new Paths() .addPathItem("/foo", new PathItem() .description("the foo path") .get(new Operation() .addParametersItem(new QueryParameter() .description("Records to skip") .required(false) .schema(new IntegerSchema() )) .responses(new ApiResponses() .addApiResponse("200", new ApiResponse() .description("it worked") .content(new Content() .addMediaType("application/json", new MediaType().schema(new Schema() .$ref("#/components/schemas/Address"))) ) .addLink("funky", new Link() .operationId("getFunky"))) ) ) ) ); LOGGER.debug(writeJson(oai)); } public static String writeJson(Object value) throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); return mapper.writer(new DefaultPrettyPrinter()).writeValueAsString(value); } } ================================================ FILE: modules/swagger-models/src/test/java/io/swagger/v3/oas/models/PathsTest.java ================================================ package io.swagger.v3.oas.models; import java.util.HashMap; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertNull; public class PathsTest { @Test public void testAddPathItem() { Paths paths = new Paths(); assertEquals(paths.addPathItem("foo", null), paths); } @Test public void testEquals() { Paths paths = new Paths(); assertEquals(paths, paths); assertEquals(paths, new Paths()); assertNotEquals(paths, null); assertNotEquals(paths, new String()); } @Test public void testGetExtensions1() { Paths paths = new Paths(); paths.addExtension("", null); paths.addExtension("y-", null); paths.addExtension(null, null); assertNull(paths.getExtensions()); } @Test public void testGetExtensions2() { Paths paths = new Paths(); paths.addExtension("x-", "foo"); paths.addExtension("x-", "bar"); paths.addExtension("x-", "baz"); assertEquals(paths.getExtensions(), new HashMap() {{ put("x-", "baz"); }}); } @Test public void testGetExtensions3() { Paths paths = new Paths(); HashMap hashMap = new HashMap<>(); hashMap.put("x-", "foo"); hashMap.put("x-", "bar"); hashMap.put("x-", "baz"); paths.setExtensions(hashMap); assertEquals(paths.getExtensions(), new HashMap() {{ put("x-", "baz"); }}); } @Test public void testExtensions() { Paths paths = new Paths(); HashMap hashMap = new HashMap<>(); hashMap.put("x-", "foo"); hashMap.put("x-", "bar"); hashMap.put("x-", "baz"); assertEquals(paths.extensions(hashMap), paths); } @Test public void testToString() { Paths paths = new Paths(); paths.addPathItem("foo", null); assertEquals(paths.toString(), "class Paths {\n {foo=null}\n}"); } } ================================================ FILE: modules/swagger-models/src/test/java/io/swagger/v3/oas/models/links/LinkParameterTest.java ================================================ package io.swagger.v3.oas.models.links; import java.util.HashMap; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertNull; public class LinkParameterTest { @Test public void testValue() { LinkParameter linkParameter = new LinkParameter(); linkParameter.setValue("foo"); linkParameter.setValue("bar"); linkParameter.setValue("baz"); assertEquals(linkParameter.value("bar"), linkParameter); assertEquals(linkParameter.getValue(), "bar"); } @Test public void testEquals() { LinkParameter linkParameter = new LinkParameter(); assertNotEquals(linkParameter, null); assertNotEquals(linkParameter, new String()); assertEquals(linkParameter, linkParameter); assertEquals(linkParameter, new LinkParameter()); } @Test public void testGetExtensions1() { LinkParameter linkParameter = new LinkParameter(); linkParameter.addExtension("", null); linkParameter.addExtension("y-", null); linkParameter.addExtension(null, null); assertNull(linkParameter.getExtensions()); } @Test public void testGetExtensions2() { LinkParameter linkParameter = new LinkParameter(); linkParameter.addExtension("x-", "foo"); linkParameter.addExtension("x-", "bar"); linkParameter.addExtension("x-", "baz"); assertEquals(linkParameter.getExtensions(), new HashMap() {{ put("x-", "baz"); }}); } @Test public void testGetExtensions3() { LinkParameter linkParameter = new LinkParameter(); HashMap hashMap = new HashMap<>(); hashMap.put("x-", "foo"); hashMap.put("x-", "bar"); hashMap.put("x-", "baz"); linkParameter.setExtensions(hashMap); assertEquals(linkParameter.getExtensions(), new HashMap() {{ put("x-", "baz"); }}); } @Test public void testExtensions() { LinkParameter linkParameter = new LinkParameter(); HashMap hashMap = new HashMap<>(); hashMap.put("x-", "foo"); hashMap.put("x-", "bar"); hashMap.put("x-", "baz"); assertEquals(linkParameter.extensions(hashMap), linkParameter); } @Test public void testToString() { LinkParameter linkParameter = new LinkParameter(); linkParameter.setValue("foo"); assertEquals(linkParameter.toString(), "class LinkParameter {\n}"); } } ================================================ FILE: modules/swagger-models/src/test/java/io/swagger/v3/oas/models/media/SchemaTest.java ================================================ package io.swagger.v3.oas.models.media; import org.testng.annotations.Test; import static org.testng.Assert.*; import java.math.BigDecimal; import java.util.Arrays; import java.util.HashMap; import java.util.Map; public class SchemaTest { @Test public void testEqualsWithDifferentBooleanSchemaValue() { Schema schema1 = new Schema<>(); Schema schema2 = new Schema<>(); schema1.setBooleanSchemaValue(true); schema2.setBooleanSchemaValue(false); assertFalse(schema1.equals(schema2)); assertFalse(schema2.equals(schema1)); assertNotEquals(schema1.hashCode(), schema2.hashCode()); } @Test public void testEqualsWithOneNullBooleanSchemaValue() { Schema schema1 = new Schema<>(); Schema schema2 = new Schema<>(); schema1.setBooleanSchemaValue(true); schema2.setBooleanSchemaValue(null); assertFalse(schema1.equals(schema2)); assertFalse(schema2.equals(schema1)); assertNotEquals(schema1.hashCode(), schema2.hashCode()); } @Test public void testBooleanSchemaValueFalseVsTrue() { // This test specifically addresses the issue where false gets mapped to true Schema schemaFalse = new Schema<>(); Schema schemaTrue = new Schema<>(); schemaFalse.setBooleanSchemaValue(false); schemaTrue.setBooleanSchemaValue(true); // These should be different assertFalse(schemaFalse.equals(schemaTrue)); assertFalse(schemaTrue.equals(schemaFalse)); // Hash codes should be different to prevent collisions in maps assertNotEquals(schemaFalse.hashCode(), schemaTrue.hashCode()); // Verify the actual values assertEquals(Boolean.FALSE, schemaFalse.getBooleanSchemaValue()); assertEquals(Boolean.TRUE, schemaTrue.getBooleanSchemaValue()); } @Test public void testComplexSchemaEqualsWithBooleanSchemaValue() { Schema schema1 = createComplexSchema(); Schema schema2 = createComplexSchema(); // Initially they should be equal assertTrue(schema1.equals(schema2)); assertEquals(schema1.hashCode(), schema2.hashCode()); // Change only booleanSchemaValue schema2.setBooleanSchemaValue(false); // Now they should be different assertFalse(schema1.equals(schema2)); assertNotEquals(schema1.hashCode(), schema2.hashCode()); } @Test public void testBooleanSchemaValueInMapLookup() { Map, String> visitedMap = new HashMap<>(); Schema schemaTrue = new Schema<>(); Schema schemaFalse = new Schema<>(); schemaTrue.setBooleanSchemaValue(true); schemaFalse.setBooleanSchemaValue(false); visitedMap.put(schemaTrue, "true_schema"); visitedMap.put(schemaFalse, "false_schema"); assertEquals(visitedMap.size(), 2); assertEquals(visitedMap.get(schemaTrue), "true_schema"); assertEquals(visitedMap.get(schemaFalse), "false_schema"); Schema anotherTrue = new Schema<>(); anotherTrue.setBooleanSchemaValue(true); assertEquals(visitedMap.get(anotherTrue), "true_schema"); Schema anotherFalse = new Schema<>(); anotherFalse.setBooleanSchemaValue(false); assertEquals(visitedMap.get(anotherFalse), "false_schema"); } @Test public void testSchemaResolutionWithBooleanSchemaValue() { Map, Schema> visitedMap = new HashMap<>(); // Create a schema with booleanSchemaValue = false Schema originalSchema = new Schema<>(); originalSchema.setBooleanSchemaValue(false); originalSchema.setTitle("Original Schema"); originalSchema.setType("boolean"); // Create a resolved version of the same schema Schema resolvedSchema = new Schema<>(); resolvedSchema.setBooleanSchemaValue(false); resolvedSchema.setTitle("Resolved Schema"); resolvedSchema.setType("boolean"); // Put the original schema in the visited map visitedMap.put(originalSchema, resolvedSchema); // Create another schema with identical structure but booleanSchemaValue = true Schema differentSchema = new Schema<>(); differentSchema.setBooleanSchemaValue(true); differentSchema.setTitle("Original Schema"); differentSchema.setType("boolean"); // The lookup should NOT return the resolved schema for the different schema assertNull(visitedMap.get(differentSchema)); // But it should return the resolved schema for an equivalent schema with false value Schema equivalentSchema = new Schema<>(); equivalentSchema.setBooleanSchemaValue(false); equivalentSchema.setTitle("Original Schema"); equivalentSchema.setType("boolean"); assertEquals(resolvedSchema, visitedMap.get(equivalentSchema)); // Verify that the schemas with different booleanSchemaValue are indeed different assertNotEquals(originalSchema, differentSchema); assertNotEquals(originalSchema.hashCode(), differentSchema.hashCode()); } @Test public void testBooleanSchemaValueInSetOperations() { java.util.Set> schemaSet = new java.util.HashSet<>(); Schema schemaTrue = new Schema<>(); schemaTrue.setBooleanSchemaValue(true); Schema schemaFalse = new Schema<>(); schemaFalse.setBooleanSchemaValue(false); schemaSet.add(schemaTrue); schemaSet.add(schemaFalse); // Should have two distinct schemas in the set assertEquals(schemaSet.size(), 2); assertTrue(schemaSet.contains(schemaTrue)); assertTrue(schemaSet.contains(schemaFalse)); // Adding equivalent schemas should not increase the set size Schema anotherTrue = new Schema<>(); anotherTrue.setBooleanSchemaValue(true); schemaSet.add(anotherTrue); assertEquals(schemaSet.size(), 2); } private Schema createComplexSchema() { Schema schema = new Schema<>(); schema.setTitle("Complex Schema"); schema.setType("object"); schema.setDescription("A complex schema for testing"); schema.setMaximum(new BigDecimal("100")); schema.setMinimum(new BigDecimal("0")); schema.setRequired(Arrays.asList("id", "name")); schema.setBooleanSchemaValue(true); return schema; } } ================================================ FILE: modules/swagger-project-jakarta/.gitignore ================================================ build/ lib/*.jar target .idea .idea_modules .settings .project .classpath .cache atlassian-ide-plugin.xml *.iml .java-version sonar-project.properties test-output/ *.pyc **/transformed/*.jar **/transformed/*.test-jar **/transformed/*.maven-plugin ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-annotations-jakarta/pom.xml ================================================ io.swagger.core.v3 swagger-project-jakarta 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-annotations-jakarta swagger-annotations-jakarta swagger-annotations-jakarta org.eclipse.transformer transformer-maven-plugin ${transformer-maven-plugin-version} true true ${project.build.finalName}-jakarta default-jar jar ${project.groupId} swagger-annotations ${project.version} javadoc-jar jar ${project.groupId} swagger-annotations ${project.version} javadoc source-jar jar ${project.groupId} swagger-annotations ${project.version} sources ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-core-jakarta/pom.xml ================================================ io.swagger.core.v3 swagger-project-jakarta 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-core-jakarta swagger-core-jakarta swagger-core-jakarta org.eclipse.transformer transformer-maven-plugin ${transformer-maven-plugin-version} true true ${project.build.finalName}-jakarta default-jar jar ${project.groupId} swagger-core ${project.version} javadoc-jar jar ${project.groupId} swagger-core ${project.version} javadoc source-jar jar ${project.groupId} swagger-core ${project.version} sources org.apache.commons commons-lang3 org.slf4j slf4j-api ch.qos.logback logback-classic provided ch.qos.logback logback-core provided commons-io commons-io io.swagger.core.v3 swagger-annotations-jakarta ${project.parent.version} io.swagger.core.v3 swagger-models-jakarta ${project.parent.version} org.yaml snakeyaml ${snakeyaml-version} jakarta.xml.bind jakarta.xml.bind-api jakarta.validation jakarta.validation-api com.fasterxml.jackson.core jackson-annotations com.fasterxml.jackson.core jackson-databind com.fasterxml.jackson.dataformat jackson-dataformat-yaml com.fasterxml.jackson.datatype jackson-datatype-jsr310 ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-integration-jakarta/pom.xml ================================================ io.swagger.core.v3 swagger-project-jakarta 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-integration-jakarta swagger-integration-jakarta swagger-integration-jakarta org.eclipse.transformer transformer-maven-plugin ${transformer-maven-plugin-version} true true ${project.build.finalName}-jakarta default-jar jar ${project.groupId} swagger-integration ${project.version} javadoc-jar jar ${project.groupId} swagger-integration ${project.version} javadoc source-jar jar ${project.groupId} swagger-integration ${project.version} sources io.github.classgraph classgraph io.swagger.core.v3 swagger-core-jakarta ${project.version} io.swagger.core.v3 swagger-models-jakarta ${project.version} ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-jaxrs2-jakarta/pom.xml ================================================ io.swagger.core.v3 swagger-project-jakarta 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-jaxrs2-jakarta swagger-jaxrs2-jakarta swagger-jaxrs2-jakarta org.eclipse.transformer transformer-maven-plugin ${transformer-maven-plugin-version} true true ${project.build.finalName}-jakarta default-jar jar ${project.groupId} swagger-jaxrs2 ${project.version} javadoc-jar jar ${project.groupId} swagger-jaxrs2 ${project.version} javadoc source-jar jar ${project.groupId} swagger-jaxrs2 ${project.version} sources ch.qos.logback logback-classic provided ch.qos.logback logback-core provided io.github.classgraph classgraph org.javassist javassist 3.30.2-GA commons-io commons-io io.swagger.core.v3 swagger-models-jakarta ${project.version} io.swagger.core.v3 swagger-annotations-jakarta ${project.version} io.swagger.core.v3 swagger-integration-jakarta ${project.version} org.yaml snakeyaml ${snakeyaml-version} jakarta.ws.rs jakarta.ws.rs-api provided jakarta.servlet jakarta.servlet-api provided com.fasterxml.jackson.core jackson-databind com.fasterxml.jackson.jakarta.rs jackson-jakarta-rs-json-provider ${jackson-version} ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-jakarta/pom.xml ================================================ io.swagger.core.v3 swagger-project-jakarta 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-jaxrs2-servlet-initializer-jakarta swagger-jaxrs2-servlet-initializer-jakarta swagger-jaxrs2-servlet-initializer-jakarta org.eclipse.transformer transformer-maven-plugin ${transformer-maven-plugin-version} true true ${project.build.finalName}-jakarta default-jar jar ${project.groupId} swagger-jaxrs2-servlet-initializer ${project.version} javadoc-jar jar ${project.groupId} swagger-jaxrs2-servlet-initializer ${project.version} javadoc source-jar jar ${project.groupId} swagger-jaxrs2-servlet-initializer ${project.version} sources ch.qos.logback logback-classic provided ch.qos.logback logback-core provided io.swagger.core.v3 swagger-jaxrs2-jakarta ${project.version} provided jakarta.ws.rs jakarta.ws.rs-api provided jakarta.servlet jakarta.servlet-api provided ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-jaxrs2-servlet-initializer-v2-jakarta/pom.xml ================================================ io.swagger.core.v3 swagger-project-jakarta 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-jaxrs2-servlet-initializer-v2-jakarta swagger-jaxrs2-servlet-initializer-v2-jakarta swagger-jaxrs2-servlet-initializer-v2-jakarta org.eclipse.transformer transformer-maven-plugin ${transformer-maven-plugin-version} true true ${project.build.finalName}-jakarta default-jar jar ${project.groupId} swagger-jaxrs2-servlet-initializer-v2 ${project.version} javadoc-jar jar ${project.groupId} swagger-jaxrs2-servlet-initializer-v2 ${project.version} javadoc source-jar jar ${project.groupId} swagger-jaxrs2-servlet-initializer-v2 ${project.version} sources ch.qos.logback logback-classic provided ch.qos.logback logback-core provided io.swagger.core.v3 swagger-jaxrs2-jakarta ${project.version} provided jakarta.ws.rs jakarta.ws.rs-api provided jakarta.servlet jakarta.servlet-api provided ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/pom.xml ================================================ io.swagger.core.v3 swagger-project-jakarta 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-maven-plugin-jakarta maven-plugin swagger-maven-plugin-jakarta swagger-maven-plugin-jakarta org.apache.maven.plugins maven-dependency-plugin 3.6.1 get-original-artifacts generate-resources copy io.swagger.core.v3 swagger-maven-plugin ${project.version} sources jar ${project.build.directory} ${project.artifactId}-${project.version}-sources.jar io.swagger.core.v3 swagger-maven-plugin ${project.version} javadoc jar ${project.build.directory} ${project.artifactId}-${project.version}-javadoc.jar com.coderplus.maven.plugins copy-rename-maven-plugin 1.0.1 copy-file compile rename true true ${project.basedir}/transformed/${project.artifactId}-${project.version}.maven-plugin ${project.basedir}/transformed/${project.artifactId}-${project.version}.jar maven-resources-plugin 3.1.0 copy-resources package copy-resources ${project.build.directory} true transformed false ${project.artifactId}-${project.version}.jar org.codehaus.mojo exec-maven-plugin 1.6.0 package java io.swagger.v3.plugin.maven.jakarta.JakartaTransformer ${project.build.directory}/${project.artifactId}-${project.version}.jar ${project.build.directory}/transformertemp ${jakarta.ws-version} ${jakarta.activation-api-version} ${jackson-version} org.apache.maven.plugins maven-plugin-plugin 3.7.0 true mojo-descriptor descriptor org.codehaus.mojo build-helper-maven-plugin 3.4.0 attach-artifacts package attach-artifact ${project.build.directory}/${project.artifactId}-${project.version}-sources.jar jar sources ${project.build.directory}/${project.artifactId}-${project.version}-javadoc.jar jar javadoc org.apache.maven maven-plugin-api ${maven.version} provided org.codehaus.plexus plexus-utils org.codehaus.plexus plexus-component-annotations org.codehaus.plexus plexus-classworlds org.apache.maven maven-core ${maven.version} provided org.codehaus.plexus plexus-utils org.apache.maven.plugin-tools maven-plugin-annotations 3.15.1 provided org.apache.maven maven-artifact org.apache.commons commons-lang3 ${commons-lang-version} org.codehaus.plexus plexus-utils 3.6.0 org.codehaus.plexus plexus-component-annotations 2.2.0 io.swagger.core.v3 swagger-jaxrs2-jakarta ${project.version} UTF-8 3.9.9 ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/src/main/java/io/swagger/v3/plugin/maven/jakarta/JakartaTransformer.java ================================================ package io.swagger.v3.plugin.maven.jakarta; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.URI; import java.nio.file.CopyOption; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; /** * Transforms swagger-maven-plugin jar file to be used with Jakarta namespace using artifactId swagger-maven-plugin-jakarta * */ public class JakartaTransformer { private static final Logger LOGGER = LoggerFactory.getLogger(JakartaTransformer.class); /* * Substitution tokens + regex */ private static Set files = Stream.of( // "META-INF/MANIFEST.MF", "META-INF/maven/plugin.xml", "META-INF/maven/io.swagger.core.v3/swagger-maven-plugin/plugin-help.xml", // "META-INF/plexus/components.xml", "META-INF/maven/io.swagger.core.v3/swagger-maven-plugin/pom.xml", "META-INF/maven/io.swagger.core.v3/swagger-maven-plugin/pom.properties") .collect(Collectors.toCollection(HashSet::new)); private static final String jakartaXmlBindDep = "\n" + " jakarta.xml.bind\n" + " jakarta.xml.bind-api\n" + " VERSION\n" + " \n"; private static final String jakartaXmlBindRegex = "^.*(.*jakarta\\.xml\\.bind((?!).)*).*$"; private static final String jakartaValidationDep = "\n" + " jakarta.validation\n" + " jakarta.validation-api\n" + " VERSION\n" + " \n"; private static final String jakartaValidationRegex = "^.*(.*jakarta\\.validation((?!).)*).*$"; private static final String jacksonJsonDep = "\n" + " com.fasterxml.jackson.jakarta.rs\n" + " jackson-jakarta-rs-json-provider\n" + " VERSION\n" + " \n" + " \n" + " jakarta.activation\n" + " jakarta.activation-api\n" + " \n" + " \n" + " jakarta.xml.bind\n" + " jakarta.xml.bind-api\n" + " \n" + " \n" + " "; private static final String jacksonJsonRegex = "^.*(.*jackson\\-jaxrs\\-json((?!).)*).*$"; private static final String jacksonBaseDep = "\n" + " com.fasterxml.jackson.jakarta.rs\n" + " jackson-jakarta-rs-base\n" + " VERSION\n" + " "; private static final String jacksonBaseRegex = "^.*(.*jackson\\-jaxrs\\-base((?!).)*).*$"; private static final String jacksonJaxbDep = "\n" + " com.fasterxml.jackson.module\n" + " jackson-module-jakarta-xmlbind-annotations\n" + " VERSION\n" + " \n" + " \n" + " jakarta.activation\n" + " jakarta.activation-api\n" + " \n" + " \n" + " jakarta.xml.bind\n" + " jakarta.xml.bind-api\n" + " \n" + " \n" + " com.sun.activation\n" + " jakarta.activation\n" + " " + " \n" + " "; private static final String jacksonJaxbRegex = "^.*(.*jackson\\-module\\-jaxb((?!).)*).*$"; private static final String jakartaActivationDep = "\n" + " jakarta.activation\n" + " jakarta.activation-api\n" + " VERSION\n" + " "; private static final String jakartaActivationRegex = "^.*(.*jakarta\\.activation((?!).)*).*$"; /** * * Extracts Jar into temp directory * */ private static void extract(String inPath, String outPath) throws Exception { Path target = Paths.get(outPath); Path source = Paths.get(inPath); try (ZipInputStream zis = new ZipInputStream(new FileInputStream(source.toFile()))) { ZipEntry zipEntry = zis.getNextEntry(); while (zipEntry != null) { Path path = target.resolve(zipEntry.getName()).normalize(); if (!path.startsWith(target + File.separator)) { throw new IOException("Entry is outside of the target dir: " + zipEntry.getName()); } if (zipEntry.isDirectory()) { if (!Files.isDirectory(path)) { Files.createDirectories(path); } } else { // fix for Windows-created archives Path parent = path.getParent(); if (!Files.isDirectory(parent)) { Files.createDirectories(parent); } // write file content try (OutputStream os = Files.newOutputStream(path)) { byte[] buffer = new byte[1024]; int len; while ((len = zis.read(buffer)) > 0) { os.write(buffer, 0, len); } } } zipEntry = zis.getNextEntry(); } zis.closeEntry(); } } /** * * Compress temp directory back into Jar after transformed * */ public static void jar(Path sourcePath, String outJarPath) throws IOException { URI uri = URI.create("jar:" + Paths.get(outJarPath).normalize().toUri()); Files.walkFileTree(sourcePath, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { if (attributes.isSymbolicLink()) { return FileVisitResult.CONTINUE; } Map env = new HashMap<>(); env.put("create", "true"); try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) { Path targetFile = sourcePath.relativize(file); Path pathInZipfile = zipfs.getPath(targetFile.toString()); if (pathInZipfile.getParent() != null) { Files.createDirectories(pathInZipfile.getParent()); } CopyOption[] options = { StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES, LinkOption.NOFOLLOW_LINKS }; Files.copy(file, pathInZipfile, options); } catch (IOException e) { LOGGER.error("Error copying file '{}' into ZIP filesystem", file, e); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) { // return FileVisitResult.CONTINUE; } }); } /** * * Replaces swagger artifact adding `-jakarta` suffix * */ private static void replaceInJar(String filePath) throws Exception { try (FileInputStream fis = new FileInputStream(filePath); BufferedInputStream bis = new BufferedInputStream(fis); ZipInputStream zis = new ZipInputStream(bis); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(filePath + ".jar"))) { for (ZipEntry zipEntry; (zipEntry = zis.getNextEntry()) != null; ) { out.putNextEntry(new ZipEntry(zipEntry.getName())); if (files.contains(zipEntry.getName())) { BufferedReader reader = new BufferedReader(new InputStreamReader(zis)); PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out))); for (String line; (line = reader.readLine()) != null; ) { line = line.replace("swagger-maven-plugin", "swagger-maven-plugin-jakarta"); line = line.replace("swagger-project", "swagger-project-jakarta"); line = line.replace("swagger-jaxrs2", "swagger-jaxrs2-jakarta"); line = line.replace("swagger-models", "swagger-models-jakarta"); line = line.replace("swagger-annotations", "swagger-annotations-jakarta"); line = line.replace("swagger-core", "swagger-core-jakarta"); line = line.replace("swagger-integration", "swagger-integration-jakarta"); writer.println(line); } writer.flush(); } else { byte[] buf = new byte[8192]; int length; while ((length = zis.read(buf)) > 0) { out.write(buf, 0, length); } } } } Files.delete(Paths.get(filePath)); Files.move(Paths.get(filePath + ".jar"), Paths.get(filePath)); } public static void main(String[] args) throws Exception { String filePath = args[0]; String outPath = args[1]; String jakartaVersion = args[2]; String jakartaActivationVersion = args[3]; String jacksonVersion = args[4]; replaceInJar(filePath); extract(filePath, outPath); // rename dir Files.move(Paths.get(outPath + File.separator + "META-INF" + File.separator + "maven" + File.separator + "io.swagger.core.v3" + File.separator + "swagger-maven-plugin"), Paths.get(outPath + File.separator + "META-INF" + File.separator + "maven" + File.separator + "io.swagger.core.v3" + File.separator + "swagger-maven-plugin-jakarta") ); Path pluginXmlPath = Paths.get( outPath + File.separator + "META-INF" + File.separator + "maven" + File.separator + "plugin.xml"); String pluginXml = new String(Files.readAllBytes(pluginXmlPath)); Matcher m = Pattern.compile(jakartaXmlBindRegex, Pattern.DOTALL).matcher(pluginXml); while (m.find()) { pluginXml = pluginXml.substring(m.start(), m.start(1)) + jakartaXmlBindDep.replace("VERSION", jakartaVersion) + pluginXml.substring(m.end(1), m.end()); } m = Pattern.compile(jakartaValidationRegex, Pattern.DOTALL).matcher(pluginXml); while (m.find()) { pluginXml = pluginXml.substring(m.start(), m.start(1)) + jakartaValidationDep.replace("VERSION", jakartaVersion) + pluginXml.substring(m.end(1), m.end()); } m = Pattern.compile(jacksonJsonRegex, Pattern.DOTALL).matcher(pluginXml); while (m.find()) { pluginXml = pluginXml.substring(m.start(), m.start(1)) + jacksonJsonDep.replace("VERSION", jacksonVersion) + pluginXml.substring(m.end(1), m.end()); } m = Pattern.compile(jacksonBaseRegex, Pattern.DOTALL).matcher(pluginXml); while (m.find()) { pluginXml = pluginXml.substring(m.start(), m.start(1)) + jacksonBaseDep.replace("VERSION", jacksonVersion) + pluginXml.substring(m.end(1), m.end()); } m = Pattern.compile(jacksonJaxbRegex, Pattern.DOTALL).matcher(pluginXml); while (m.find()) { pluginXml = pluginXml.substring(m.start(), m.start(1)) + jacksonJaxbDep.replace("VERSION", jacksonVersion) + pluginXml.substring(m.end(1), m.end()); } m = Pattern.compile(jakartaActivationRegex, Pattern.DOTALL).matcher(pluginXml); while (m.find()) { pluginXml = pluginXml.substring(m.start(), m.start(1)) + jakartaActivationDep.replace("VERSION", jakartaActivationVersion) + pluginXml.substring(m.end(1), m.end()); } // write back to plugin.xml file Files.write(pluginXmlPath, pluginXml.getBytes()); // delete the original jar Files.delete(Paths.get(filePath)); // compress the new jar jar(Paths.get(outPath), filePath); // delete the temp directory Files.walk(Paths.get(outPath)) .sorted(Comparator.reverseOrder()) .map(Path::toFile) .forEach(File::delete); } } ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-maven-plugin-jakarta/transformed/README.md ================================================ #### Don't delete Target directory for eclipse transformer plugin; Jakarta EE 9+ artifacts are generated in this directory ================================================ FILE: modules/swagger-project-jakarta/modules/swagger-models-jakarta/pom.xml ================================================ io.swagger.core.v3 swagger-project-jakarta 2.2.46-SNAPSHOT ../.. 4.0.0 swagger-models-jakarta swagger-models-jakarta swagger-models-jakarta org.eclipse.transformer transformer-maven-plugin ${transformer-maven-plugin-version} true true ${project.build.finalName}-jakarta default-jar jar ${project.groupId} swagger-models ${project.version} javadoc-jar jar ${project.groupId} swagger-models ${project.version} javadoc source-jar jar ${project.groupId} swagger-models ${project.version} sources com.fasterxml.jackson.core jackson-annotations ================================================ FILE: modules/swagger-project-jakarta/pom.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-project-jakarta pom swagger-project-jakarta swagger-project-jakarta 2.2.46-SNAPSHOT https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git scm:git:git@github.com:swagger-api/swagger-core.git https://github.com/swagger-api/swagger-core 2.2.0 frantuma Francesco Tumanischvili frantuma@yahoo.com github https://github.com/swagger-api/swagger-core/issues swagger-swaggersocket https://groups.google.com/forum/#!forum/swagger-swaggersocket Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0.html repo install target ${project.artifactId}-${project.version} META-INF ../../../.. true NOTICE LICENSE maven-compiler-plugin 3.11.0 org.apache.maven.plugins maven-enforcer-plugin ${enforcer-plugin-version} enforce-versions enforce true No Snapshots Allowed! (,2.1.0),(2.1.0,2.2.0),(2.2.0,) Maven 2.1.0 and 2.2.0 produce incorrect GPG signatures and checksums respectively. maven-dependency-plugin copy-deps package copy-dependencies ${project.build.directory}/lib org.sonatype.central central-publishing-maven-plugin 0.7.0 true central true published 3600 org.apache.maven.plugins maven-gpg-plugin 1.6 --pinentry-mode loopback org.eclipse.jetty jetty-maven-plugin ${jetty-version} org.glassfish.jersey.core jersey-server ${jersey2-version} org.javassist javassist org.glassfish.jersey.containers jersey-container-servlet ${jersey2-version} org.javassist javassist org.glassfish.jersey.media jersey-media-multipart ${jersey2-version} org.javassist javassist org.glassfish.jersey.inject jersey-hk2 ${jersey2-version} org.javassist javassist org.apache.maven.plugins maven-enforcer-plugin ${enforcer-plugin-version} release org.apache.maven.plugins maven-gpg-plugin 1.6 --pinentry-mode loopback sign-artifacts verify sign modules/swagger-annotations-jakarta modules/swagger-models-jakarta modules/swagger-core-jakarta modules/swagger-integration-jakarta modules/swagger-jaxrs2-jakarta modules/swagger-jaxrs2-servlet-initializer-jakarta modules/swagger-jaxrs2-servlet-initializer-v2-jakarta modules/swagger-maven-plugin-jakarta target/site org.apache.maven.plugins maven-javadoc-plugin 3.6.2 true 1.8 UTF-8 1g true https://docs.oracle.com/javase/8/docs/api org.apache.maven.plugins maven-jxr-plugin 2.5 true org.apache.maven.plugins maven-project-info-reports-plugin 2.9 project-team org.apache.maven maven-plugin-tools-api 3.5.1 org.slf4j slf4j-api ${slf4j-version} compile org.slf4j slf4j-ext ${slf4j-version} compile org.slf4j slf4j-log4j12 ${slf4j-version} provided org.apache.commons commons-lang3 ${commons-lang-version} compile org.apache.httpcomponents httpclient ${httpcomponents-version} commons-io commons-io ${commons-io-version} test io.github.classgraph classgraph ${classgraph-version} ch.qos.logback logback-classic ${logback-version} provided ch.qos.logback logback-core ${logback-version} provided joda-time joda-time ${joda-time-version} org.joda joda-convert ${joda-version} org.yaml snakeyaml ${snakeyaml-version} jakarta.servlet jakarta.servlet-api ${servlet-api-version} provided jakarta.xml.bind jakarta.xml.bind-api ${jakarta.xml.bind-api-version} jakarta.activation jakarta.activation-api ${jakarta.activation-api-version} jakarta.ws.rs jakarta.ws.rs-api ${jakarta.ws-version} jakarta.validation jakarta.validation-api ${jakarta.validation-version} com.fasterxml.jackson.core jackson-annotations ${jackson-annotations-version} com.fasterxml.jackson.core jackson-core ${jackson-version} com.fasterxml.jackson.core jackson-databind ${jackson-databind-version} jakarta.activation jakarta.activation-api jakarta.xml.bind jakarta.xml.bind-api com.fasterxml.jackson.dataformat jackson-dataformat-yaml ${jackson-version} com.fasterxml.jackson.datatype jackson-datatype-jsr310 ${jackson-version} com.fasterxml.jackson.jakarta.rs jackson-jakarta-rs-json-provider ${jackson-version} jakarta.activation jakarta.activation-api jakarta.xml.bind jakarta.xml.bind-api com.fasterxml.jackson.jakarta.rs jackson-jakarta-rs-base ${jackson-version} com.fasterxml.jackson.module jackson-module-jakarta-xmlbind-annotations ${jackson-version} jakarta.activation jakarta.activation-api jakarta.xml.bind jakarta.xml.bind-api com.sun.activation jakarta.activation com.google.guava guava ${guava-version} test 8 2.2.4 2.13.0 2.3 3.1.0 3.0.2 3.0.1 2.1.3 6.4.0 5.0.0 3.1.10 2.21.1 2.21 2.21.1 1.5.25 4.8.184 32.1.3-jre 1.10.15 3.20.0 2.18.0 2.0.9 9.4.56.v20240826g 7.9.0 2.28.2 4.5.1 4.5.14 1.17.2 2.22.2 3.2.1 2.22.2 0.90 0.90 0 UTF-8 0.5.0 3.9.9 1.27.1 ================================================ FILE: mvnw ================================================ #!/bin/sh # ---------------------------------------------------------------------------- # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- # Apache Maven Wrapper startup batch script, version 3.2.0 # # Required ENV vars: # ------------------ # JAVA_HOME - location of a JDK home dir # # Optional ENV vars # ----------------- # MAVEN_OPTS - parameters passed to the Java VM when running Maven # e.g. to debug Maven itself, use # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 # MAVEN_SKIP_RC - flag to disable loading of mavenrc files # ---------------------------------------------------------------------------- if [ -z "$MAVEN_SKIP_RC" ] ; then if [ -f /usr/local/etc/mavenrc ] ; then . /usr/local/etc/mavenrc fi if [ -f /etc/mavenrc ] ; then . /etc/mavenrc fi if [ -f "$HOME/.mavenrc" ] ; then . "$HOME/.mavenrc" fi fi # OS specific support. $var _must_ be set to either true or false. cygwin=false; darwin=false; mingw=false case "$(uname)" in CYGWIN*) cygwin=true ;; MINGW*) mingw=true;; Darwin*) darwin=true # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home # See https://developer.apple.com/library/mac/qa/qa1170/_index.html if [ -z "$JAVA_HOME" ]; then if [ -x "/usr/libexec/java_home" ]; then JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME else JAVA_HOME="/Library/Java/Home"; export JAVA_HOME fi fi ;; esac if [ -z "$JAVA_HOME" ] ; then if [ -r /etc/gentoo-release ] ; then JAVA_HOME=$(java-config --jre-home) fi fi # For Cygwin, ensure paths are in UNIX format before anything is touched if $cygwin ; then [ -n "$JAVA_HOME" ] && JAVA_HOME=$(cygpath --unix "$JAVA_HOME") [ -n "$CLASSPATH" ] && CLASSPATH=$(cygpath --path --unix "$CLASSPATH") fi # For Mingw, ensure paths are in UNIX format before anything is touched if $mingw ; then [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" fi if [ -z "$JAVA_HOME" ]; then javaExecutable="$(which javac)" if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then # readlink(1) is not available as standard on Solaris 10. readLink=$(which readlink) if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then if $darwin ; then javaHome="$(dirname "\"$javaExecutable\"")" javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" else javaExecutable="$(readlink -f "\"$javaExecutable\"")" fi javaHome="$(dirname "\"$javaExecutable\"")" javaHome=$(expr "$javaHome" : '\(.*\)/bin') JAVA_HOME="$javaHome" export JAVA_HOME fi fi fi if [ -z "$JAVACMD" ] ; then 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 else JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" fi fi if [ ! -x "$JAVACMD" ] ; then echo "Error: JAVA_HOME is not defined correctly." >&2 echo " We cannot execute $JAVACMD" >&2 exit 1 fi if [ -z "$JAVA_HOME" ] ; then echo "Warning: JAVA_HOME environment variable is not set." fi # traverses directory structure from process work directory to filesystem root # first directory with .mvn subdirectory is considered project base directory find_maven_basedir() { if [ -z "$1" ] then echo "Path not specified to find_maven_basedir" return 1 fi basedir="$1" wdir="$1" while [ "$wdir" != '/' ] ; do if [ -d "$wdir"/.mvn ] ; then basedir=$wdir break fi # workaround for JBEAP-8937 (on Solaris 10/Sparc) if [ -d "${wdir}" ]; then wdir=$(cd "$wdir/.." || exit 1; pwd) fi # end of workaround done printf '%s' "$(cd "$basedir" || exit 1; pwd)" } # concatenates all lines of a file concat_lines() { if [ -f "$1" ]; then # Remove \r in case we run on Windows within Git Bash # and check out the repository with auto CRLF management # enabled. Otherwise, we may read lines that are delimited with # \r\n and produce $'-Xarg\r' rather than -Xarg due to word # splitting rules. tr -s '\r\n' ' ' < "$1" fi } log() { if [ "$MVNW_VERBOSE" = true ]; then printf '%s\n' "$1" fi } BASE_DIR=$(find_maven_basedir "$(dirname "$0")") if [ -z "$BASE_DIR" ]; then exit 1; fi MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR log "$MAVEN_PROJECTBASEDIR" ########################################################################################## # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central # This allows using the maven wrapper in projects that prohibit checking in binary data. ########################################################################################## wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" if [ -r "$wrapperJarPath" ]; then log "Found $wrapperJarPath" else log "Couldn't find $wrapperJarPath, downloading it ..." if [ -n "$MVNW_REPOURL" ]; then wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" else wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" fi while IFS="=" read -r key value; do # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) safeValue=$(echo "$value" | tr -d '\r') case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; esac done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" log "Downloading from: $wrapperUrl" if $cygwin; then wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") fi if command -v wget > /dev/null; then log "Found wget ... using wget" [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" else wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" fi elif command -v curl > /dev/null; then log "Found curl ... using curl" [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" else curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" fi else log "Falling back to using Java to download" javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" # For Cygwin, switch paths to Windows format before running javac if $cygwin; then javaSource=$(cygpath --path --windows "$javaSource") javaClass=$(cygpath --path --windows "$javaClass") fi if [ -e "$javaSource" ]; then if [ ! -e "$javaClass" ]; then log " - Compiling MavenWrapperDownloader.java ..." ("$JAVA_HOME/bin/javac" "$javaSource") fi if [ -e "$javaClass" ]; then log " - Running MavenWrapperDownloader.java ..." ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" fi fi fi fi ########################################################################################## # End of extension ########################################################################################## # If specified, validate the SHA-256 sum of the Maven wrapper jar file wrapperSha256Sum="" while IFS="=" read -r key value; do case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; esac done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" if [ -n "$wrapperSha256Sum" ]; then wrapperSha256Result=false if command -v sha256sum > /dev/null; then if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then wrapperSha256Result=true fi elif command -v shasum > /dev/null; then if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then wrapperSha256Result=true fi else echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." exit 1 fi if [ $wrapperSha256Result = false ]; then echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 exit 1 fi fi MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java if $cygwin; then [ -n "$JAVA_HOME" ] && JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") [ -n "$CLASSPATH" ] && CLASSPATH=$(cygpath --path --windows "$CLASSPATH") [ -n "$MAVEN_PROJECTBASEDIR" ] && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") fi # Provide a "standardized" way to retrieve the CLI args that will # work with both Windows and non-Windows executions. MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" export MAVEN_CMD_LINE_ARGS WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain # shellcheck disable=SC2086 # safe args exec "$JAVACMD" \ $MAVEN_OPTS \ $MAVEN_DEBUG_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" ================================================ FILE: mvnw.cmd ================================================ @REM ---------------------------------------------------------------------------- @REM Licensed to the Apache Software Foundation (ASF) under one @REM or more contributor license agreements. See the NOTICE file @REM distributed with this work for additional information @REM regarding copyright ownership. The ASF licenses this file @REM to you under the Apache License, Version 2.0 (the @REM "License"); you may not use this file except in compliance @REM with the License. You may obtain a copy of the License at @REM @REM http://www.apache.org/licenses/LICENSE-2.0 @REM @REM Unless required by applicable law or agreed to in writing, @REM software distributed under the License is distributed on an @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @REM KIND, either express or implied. See the License for the @REM specific language governing permissions and limitations @REM under the License. @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- @REM Apache Maven Wrapper startup batch script, version 3.2.0 @REM @REM Required ENV vars: @REM JAVA_HOME - location of a JDK home dir @REM @REM Optional ENV vars @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven @REM e.g. to debug Maven itself, use @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files @REM ---------------------------------------------------------------------------- @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' @echo off @REM set title of command window title %0 @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% @REM set %HOME% to equivalent of $HOME if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") @REM Execute a user defined script before this one if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre @REM check for pre script, once with legacy .bat ending and once with .cmd ending if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* :skipRcPre @setlocal set ERROR_CODE=0 @REM To isolate internal variables from possible post scripts, we use another setlocal @setlocal @REM ==== START VALIDATION ==== if not "%JAVA_HOME%" == "" goto OkJHome echo. echo Error: JAVA_HOME not found in your environment. >&2 echo Please set the JAVA_HOME variable in your environment to match the >&2 echo location of your Java installation. >&2 echo. goto error :OkJHome if exist "%JAVA_HOME%\bin\java.exe" goto init echo. echo Error: JAVA_HOME is set to an invalid directory. >&2 echo JAVA_HOME = "%JAVA_HOME%" >&2 echo Please set the JAVA_HOME variable in your environment to match the >&2 echo location of your Java installation. >&2 echo. goto error @REM ==== END VALIDATION ==== :init @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". @REM Fallback to current working directory if not found. set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir set EXEC_DIR=%CD% set WDIR=%EXEC_DIR% :findBaseDir IF EXIST "%WDIR%"\.mvn goto baseDirFound cd .. IF "%WDIR%"=="%CD%" goto baseDirNotFound set WDIR=%CD% goto findBaseDir :baseDirFound set MAVEN_PROJECTBASEDIR=%WDIR% cd "%EXEC_DIR%" goto endDetectBaseDir :baseDirNotFound set MAVEN_PROJECTBASEDIR=%EXEC_DIR% cd "%EXEC_DIR%" :endDetectBaseDir IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig @setlocal EnableExtensions EnableDelayedExpansion for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% :endReadAdditionalConfig SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B ) @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central @REM This allows using the maven wrapper in projects that prohibit checking in binary data. if exist %WRAPPER_JAR% ( if "%MVNW_VERBOSE%" == "true" ( echo Found %WRAPPER_JAR% ) ) else ( if not "%MVNW_REPOURL%" == "" ( SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" ) if "%MVNW_VERBOSE%" == "true" ( echo Couldn't find %WRAPPER_JAR%, downloading it ... echo Downloading from: %WRAPPER_URL% ) powershell -Command "&{"^ "$webclient = new-object System.Net.WebClient;"^ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ "}"^ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ "}" if "%MVNW_VERBOSE%" == "true" ( echo Finished downloading %WRAPPER_JAR% ) ) @REM End of extension @REM If specified, validate the SHA-256 sum of the Maven wrapper jar file SET WRAPPER_SHA_256_SUM="" FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B ) IF NOT %WRAPPER_SHA_256_SUM%=="" ( powershell -Command "&{"^ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ " exit 1;"^ "}"^ "}" if ERRORLEVEL 1 goto error ) @REM Provide a "standardized" way to retrieve the CLI args that will @REM work with both Windows and non-Windows executions. set MAVEN_CMD_LINE_ARGS=%* %MAVEN_JAVA_EXE% ^ %JVM_CONFIG_MAVEN_PROPS% ^ %MAVEN_OPTS% ^ %MAVEN_DEBUG_OPTS% ^ -classpath %WRAPPER_JAR% ^ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* if ERRORLEVEL 1 goto error goto end :error set ERROR_CODE=1 :end @endlocal & set ERROR_CODE=%ERROR_CODE% if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost @REM check for post script, once with legacy .bat ending and once with .cmd ending if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" :skipRcPost @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' if "%MAVEN_BATCH_PAUSE%"=="on" pause if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% cmd /C exit /B %ERROR_CODE% ================================================ FILE: pom.xml ================================================ 4.0.0 io.swagger.core.v3 swagger-project pom swagger-project swagger-project 2.2.46-SNAPSHOT https://github.com/swagger-api/swagger-core scm:git:git@github.com:swagger-api/swagger-core.git scm:git:git@github.com:swagger-api/swagger-core.git https://github.com/swagger-api/swagger-core 2.2.0 frantuma Francesco Tumanischvili frantuma@yahoo.com fehguy Tony Tam fehguy@gmail.com webron Ron Ratovsky webron@gmail.com github https://github.com/swagger-api/swagger-core/issues swagger-swaggersocket https://groups.google.com/forum/#!forum/swagger-swaggersocket Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0.html repo src/main/scripts target/classes target/test-classes src/main/resources logback.xml META-INF ../.. true NOTICE LICENSE org.jvnet.wagon-svn wagon-svn 1.12 org.apache.maven.wagon wagon-ssh-external 3.5.3 org.apache.maven.wagon wagon-webdav 1.0-beta-2 install target ${project.artifactId}-${project.version} maven-compiler-plugin 3.11.0 org.apache.maven.plugins maven-enforcer-plugin ${enforcer-plugin-version} enforce-versions enforce true No Snapshots Allowed! (,2.1.0),(2.1.0,2.2.0),(2.2.0,) Maven 2.1.0 and 2.2.0 produce incorrect GPG signatures and checksums respectively. maven-dependency-plugin package copy-dependencies ${project.build.directory}/lib org.apache.maven.plugins maven-source-plugin 3.3.0 attach-sources verify jar-no-fork org.apache.maven.plugins maven-javadoc-plugin 3.6.2 true 1.8 UTF-8 1g http://docs.oracle.com/javase/8/docs/api ${javadoc.package.exclude} attach-javadocs verify jar org.apache.maven.plugins maven-jar-plugin 3.3.0 **/logback.xml development ${project.url} ${project.version} io.swagger org.apache.maven.plugins maven-site-plugin 3.12.1 org.sonatype.central central-publishing-maven-plugin 0.7.0 true central true published 3600 biz.aQute.bnd bnd-maven-plugin ${bnd-version} ="2.0";\ uses:="\ javax.ws.rs,\ javax.ws.rs.core,\ javax.ws.rs.ext,\ javax.ws.rs.client,\ javax.ws.rs.container",\ osgi.contract;\ osgi.contract=JavaServlet;\ version:List="4.0";\ uses:="\ javax.servlet,\ javax.servlet.annotation,\ javax.servlet.descriptor,\ javax.servlet.http" -cdiannotations: ]]> bnd-process org.apache.maven.plugins maven-gpg-plugin 1.6 --pinentry-mode loopback org.eclipse.jetty jetty-maven-plugin ${jetty-version} org.glassfish.jersey.core jersey-server ${jersey2-version} org.javassist javassist org.glassfish.jersey.containers jersey-container-servlet ${jersey2-version} org.javassist javassist org.glassfish.jersey.media jersey-media-multipart ${jersey2-version} org.javassist javassist org.glassfish.jersey.inject jersey-hk2 ${jersey2-version} org.javassist javassist org.apache.maven.plugins maven-enforcer-plugin ${enforcer-plugin-version} org.jacoco jacoco-maven-plugin 0.8.6 security org.owasp dependency-check-maven 6.5.3 true check release org.apache.maven.plugins maven-gpg-plugin 1.6 --pinentry-mode loopback sign-artifacts verify sign java-17-modules [17,) modules/swagger-java17-support modules/swagger-annotations modules/swagger-models modules/swagger-core modules/swagger-integration modules/swagger-jaxrs2 modules/swagger-jaxrs2-servlet-initializer modules/swagger-jaxrs2-servlet-initializer-v2 modules/swagger-maven-plugin modules/swagger-eclipse-transformer-maven-plugin modules/swagger-project-jakarta target/site org.apache.maven.plugins maven-javadoc-plugin 3.6.2 true 1.8 UTF-8 1g true https://docs.oracle.com/javase/8/docs/api org.apache.maven.plugins maven-jxr-plugin 2.5 true org.apache.maven.plugins maven-project-info-reports-plugin 2.9 project-team org.apache.maven maven-plugin-tools-api 3.5.1 org.slf4j slf4j-ext ${slf4j-version} compile org.slf4j slf4j-api ${slf4j-version} compile org.apache.commons commons-lang3 ${commons-lang-version} compile org.testng testng ${testng-version} test io.rest-assured rest-assured ${rest-assured-version} test org.apache.httpcomponents httpmime ${httpcomponents-version} test org.apache.httpcomponents httpclient ${httpcomponents-version} org.mockito mockito-core ${mockito-version} test jakarta.servlet jakarta.servlet-api ${servlet-api-version} provided jakarta.xml.bind jakarta.xml.bind-api ${jakarta.xml.bind-api-version} jakarta.activation jakarta.activation-api ${jakarta.activation-api-version} org.slf4j slf4j-log4j12 ${slf4j-version} provided commons-io commons-io ${commons-io-version} test io.github.classgraph classgraph ${classgraph-version} com.fasterxml.jackson.dataformat jackson-dataformat-yaml ${jackson-version} com.fasterxml.jackson.core jackson-annotations ${jackson-annotations-version} com.fasterxml.jackson.core jackson-databind ${jackson-databind-version} com.fasterxml.jackson.core jackson-core ${jackson-version} com.fasterxml.jackson.datatype jackson-datatype-jsr310 ${jackson-version} ch.qos.logback logback-classic ${logback-version} provided ch.qos.logback logback-core ${logback-version} provided joda-time joda-time ${joda-time-version} org.joda joda-convert ${joda-version} org.yaml snakeyaml ${snakeyaml-version} jakarta.ws.rs jakarta.ws.rs-api ${jakarta.ws-version} com.google.guava guava ${guava-version} test org.apache.ant ant ${ant-version} test commons-codec commons-codec ${commons-codec-version} test org.codehaus.groovy groovy 3.0.23 test 8 2.2.4 2.13.0 2.3 2.1.6 2.3.3 1.2.2 6.4.0 4.0.4 2.46 2.21.1 2.21 2.21.1 1.5.25 4.8.184 32.1.3-jre 1.10.15 3.20.0 2.18.0 2.0.9 9.4.56.v20240826 7.10.2 2.28.2 4.5.1 4.5.14 1.17.2 3.5.0 3.2.1 2.22.2 0.90 0.90 0 0.5.0 UTF-8