commit dfd1f365de0cbf4c630087748938523e109c51b4 Author: DopleZZ Date: Mon Sep 7 15:56:27 2026 +0300 Add OpenAPI spec and Swagger UI docs for Vehicle collection and shop services Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01Fe9ZVw7Q7JrMz1hgS2rwna diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml new file mode 100644 index 0000000..dcc3fcd --- /dev/null +++ b/openapi/openapi.yaml @@ -0,0 +1,511 @@ +openapi: 3.0.3 +info: + title: Vehicle Collection API + version: "1.0.0" + description: > + Набор из двух веб-сервисов: сервис управления коллекцией объектов Vehicle + и сервис /shop, реализующий дополнительные операции над этой коллекцией + через вызовы API первого сервиса. + license: + name: Учебный материал (лабораторная работа по курсу СОА) +servers: + - url: http://127.0.0.1:8080 + description: Сервер для разработки и тестирования +tags: + - name: Vehicles + description: Первый веб-сервис — управление коллекцией объектов Vehicle + - name: Shop + description: Второй веб-сервис (/shop) — дополнительные операции над Vehicle +security: [] + +paths: + /api/vehicles: + post: + tags: [Vehicles] + operationId: createVehicle + summary: Добавить новый элемент в коллекцию + description: > + Создаёт новый объект Vehicle. Поля id и creationDate генерируются + сервисом автоматически и в теле запроса не передаются. + requestBody: + required: true + content: + application/xml: + schema: + $ref: '#/components/schemas/VehicleInput' + responses: + '201': + description: Объект успешно создан + headers: + Location: + description: URL созданного объекта + schema: + type: string + content: + application/xml: + schema: + $ref: '#/components/schemas/Vehicle' + '400': + $ref: '#/components/responses/BadRequest' + get: + tags: [Vehicles] + operationId: getVehicles + summary: Получить массив элементов коллекции + description: > + Возвращает элементы коллекции постранично. Поддерживает сортировку + по любой комбинации полей (параметр sort) и фильтрацию по любой + комбинации полей (параметр filter). Все параметры операции + передаются в URL запроса (query-параметры). + parameters: + - $ref: '#/components/parameters/PageNumber' + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Sort' + - $ref: '#/components/parameters/Filter' + responses: + '200': + description: Страница результатов выборки + content: + application/xml: + schema: + $ref: '#/components/schemas/VehiclePage' + '400': + $ref: '#/components/responses/BadRequest' + + /api/vehicles/{id}: + parameters: + - $ref: '#/components/parameters/VehicleId' + get: + tags: [Vehicles] + operationId: getVehicleById + summary: Получить элемент коллекции по ИД + responses: + '200': + description: Найденный объект + content: + application/xml: + schema: + $ref: '#/components/schemas/Vehicle' + '404': + $ref: '#/components/responses/NotFound' + put: + tags: [Vehicles] + operationId: updateVehicle + summary: Обновить элемент коллекции + requestBody: + required: true + content: + application/xml: + schema: + $ref: '#/components/schemas/VehicleInput' + responses: + '200': + description: Объект обновлён + content: + application/xml: + schema: + $ref: '#/components/schemas/Vehicle' + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + delete: + tags: [Vehicles] + operationId: deleteVehicle + summary: Удалить элемент коллекции + responses: + '204': + description: Объект удалён + '404': + $ref: '#/components/responses/NotFound' + + /api/vehicles/by-type/{type}: + delete: + tags: [Vehicles] + operationId: deleteVehiclesByType + summary: Удалить все объекты с заданным значением поля type + parameters: + - $ref: '#/components/parameters/VehicleTypePath' + responses: + '200': + description: Результат удаления + content: + application/xml: + schema: + $ref: '#/components/schemas/DeletionResult' + '400': + $ref: '#/components/responses/BadRequest' + + /api/vehicles/by-type/{type}/any: + delete: + tags: [Vehicles] + operationId: deleteOneVehicleByType + summary: Удалить один (любой) объект с заданным значением поля type + parameters: + - $ref: '#/components/parameters/VehicleTypePath' + responses: + '200': + description: Удалённый объект + content: + application/xml: + schema: + $ref: '#/components/schemas/Vehicle' + '404': + description: Объектов с указанным значением type не найдено + content: + application/xml: + schema: + $ref: '#/components/schemas/Error' + + /api/vehicles/count/fuel-type-less-than/{fuelType}: + get: + tags: [Vehicles] + operationId: countVehiclesByFuelTypeLessThan + summary: Вернуть количество объектов, у которых fuelType меньше заданного + description: > + Значения FuelType сравниваются по порядку их объявления в перечислении + (ALCOHOL < MANPOWER < PLASMA < ANTIMATTER). Объекты с fuelType = null + в сравнении не участвуют и не учитываются в результате. + parameters: + - $ref: '#/components/parameters/FuelTypePath' + responses: + '200': + description: Количество подходящих объектов + content: + application/xml: + schema: + $ref: '#/components/schemas/CountResult' + '400': + $ref: '#/components/responses/BadRequest' + + /shop/fix-distance/{vehicle-id}: + post: + tags: [Shop] + operationId: fixDistance + summary: "\"Скрутить\" счётчик пробега транспортного средства до нуля" + description: > + Обращается к API первого сервиса и обнуляет счётчик пробега + транспортного средства с заданным id. + parameters: + - $ref: '#/components/parameters/ShopVehicleId' + responses: + '200': + description: Счётчик пробега обнулён + content: + application/xml: + schema: + $ref: '#/components/schemas/ActionResult' + '404': + $ref: '#/components/responses/NotFound' + + /shop/add-wheels/{vehicle-id}/{number-of-wheels}: + post: + tags: [Shop] + operationId: addWheels + summary: Добавить транспортному средству указанное число колёс + description: > + Обращается к API первого сервиса и увеличивает число колёс + транспортного средства с заданным id на указанное значение. + parameters: + - $ref: '#/components/parameters/ShopVehicleId' + - $ref: '#/components/parameters/NumberOfWheels' + responses: + '200': + description: Колёса добавлены + content: + application/xml: + schema: + $ref: '#/components/schemas/ActionResult' + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + +components: + parameters: + VehicleId: + name: id + in: path + required: true + description: Идентификатор объекта Vehicle + schema: + type: integer + format: int64 + minimum: 1 + + ShopVehicleId: + name: vehicle-id + in: path + required: true + description: Идентификатор транспортного средства + schema: + type: integer + format: int64 + minimum: 1 + + NumberOfWheels: + name: number-of-wheels + in: path + required: true + description: Число колёс, которое нужно добавить + schema: + type: integer + format: int32 + minimum: 1 + + VehicleTypePath: + name: type + in: path + required: true + description: Значение поля type + schema: + $ref: '#/components/schemas/VehicleType' + + FuelTypePath: + name: fuelType + in: path + required: true + description: Значение поля fuelType, с которым сравниваются объекты коллекции + schema: + $ref: '#/components/schemas/FuelType' + + PageNumber: + name: pageNumber + in: query + required: false + description: Порядковый номер выводимой страницы, нумерация начинается с 1 + schema: + type: integer + format: int32 + minimum: 1 + default: 1 + + PageSize: + name: pageSize + in: query + required: false + description: Размер страницы (количество элементов на странице) + schema: + type: integer + format: int32 + minimum: 1 + default: 10 + + Sort: + name: sort + in: query + required: false + description: > + Правило сортировки в формате "поле,направление", где направление — + asc или desc (по умолчанию asc). Параметр можно указать несколько + раз, чтобы отсортировать по нескольким полям сразу — порядок + повторений задаёт приоритет полей. Допустимые имена полей: id, name, + coordinates.x, coordinates.y, creationDate, enginePower, type, + fuelType. + style: form + explode: true + schema: + type: array + items: + type: string + pattern: '^(id|name|coordinates\.x|coordinates\.y|creationDate|enginePower|type|fuelType)(,(asc|desc))?$' + example: ["name,asc"] + + Filter: + name: filter + in: query + required: false + description: > + Условие фильтрации в формате "поле:оператор:значение". Поддерживаемые + операторы: eq, ne, gt, gte, lt, lte, like (like — только для строковых + полей, подстрока без учёта регистра). Параметр можно указать + несколько раз — все условия объединяются по И (AND), что позволяет + фильтровать по любой комбинации полей. Для проверки на отсутствие + значения используется литерал null, например enginePower:eq:null. + style: form + explode: true + schema: + type: array + items: + type: string + example: ["type:eq:PLANE"] + + responses: + NotFound: + description: Объект с указанным идентификатором не найден + content: + application/xml: + schema: + $ref: '#/components/schemas/Error' + BadRequest: + description: > + Переданные данные нарушают ограничения целостности, заданные на + уровне класса, либо параметры запроса имеют неверный формат + content: + application/xml: + schema: + $ref: '#/components/schemas/Error' + + schemas: + VehicleType: + type: string + enum: [PLANE, BOAT, SHIP] + xml: + name: VehicleType + + FuelType: + type: string + enum: [ALCOHOL, MANPOWER, PLASMA, ANTIMATTER] + xml: + name: FuelType + + Coordinates: + type: object + required: [x, y] + properties: + x: + type: integer + format: int32 + y: + type: number + format: float + exclusiveMinimum: true + minimum: -27 + xml: + name: Coordinates + + Vehicle: + type: object + required: [id, name, coordinates, creationDate] + properties: + id: + type: integer + format: int64 + minimum: 1 + readOnly: true + name: + type: string + minLength: 1 + coordinates: + $ref: '#/components/schemas/Coordinates' + creationDate: + type: string + format: date-time + readOnly: true + enginePower: + type: number + format: double + nullable: true + exclusiveMinimum: true + minimum: 0 + type: + type: string + nullable: true + allOf: + - $ref: '#/components/schemas/VehicleType' + fuelType: + type: string + nullable: true + allOf: + - $ref: '#/components/schemas/FuelType' + xml: + name: Vehicle + + VehicleInput: + type: object + required: [name, coordinates] + properties: + name: + type: string + minLength: 1 + coordinates: + $ref: '#/components/schemas/Coordinates' + enginePower: + type: number + format: double + nullable: true + exclusiveMinimum: true + minimum: 0 + type: + type: string + nullable: true + allOf: + - $ref: '#/components/schemas/VehicleType' + fuelType: + type: string + nullable: true + allOf: + - $ref: '#/components/schemas/FuelType' + xml: + name: Vehicle + + VehiclePage: + type: object + properties: + pageNumber: + type: integer + format: int32 + pageSize: + type: integer + format: int32 + totalElements: + type: integer + format: int64 + totalPages: + type: integer + format: int32 + items: + type: array + items: + $ref: '#/components/schemas/Vehicle' + xml: + name: vehicle + wrapped: true + xml: + name: VehiclePage + + DeletionResult: + type: object + properties: + deletedCount: + type: integer + format: int64 + xml: + name: DeletionResult + + CountResult: + type: object + properties: + count: + type: integer + format: int64 + xml: + name: CountResult + + ActionResult: + type: object + properties: + vehicleId: + type: integer + format: int64 + message: + type: string + xml: + name: ActionResult + + Error: + type: object + properties: + timestamp: + type: string + format: date-time + status: + type: integer + format: int32 + error: + type: string + message: + type: string + path: + type: string + xml: + name: Error diff --git a/openapi/swagger-ui/index.html b/openapi/swagger-ui/index.html new file mode 100644 index 0000000..ce870ef --- /dev/null +++ b/openapi/swagger-ui/index.html @@ -0,0 +1,24 @@ + + + + + Vehicle Collection API — документация + + + +
+ + + +