From 90da4eb95e61f75b53dd6832408ef8506b64d52b Mon Sep 17 00:00:00 2001 From: Riley Park Date: Sun, 28 Apr 2024 13:58:21 -0700 Subject: [PATCH] prepare for v3 --- .../papermc/bibliothek/api/model/Change.java | 37 ++++++ .../papermc/bibliothek/api/model/Channel.java | 29 +++++ .../bibliothek/api/model/Download.java | 35 ++++++ .../api/response/v2/BuildResponse.java | 77 ++++++++++++ .../api/response/v2/BuildsResponse.java | 81 ++++++++++++ .../api/response/v2/ProjectResponse.java | 48 +++++++ .../api/response/v2/ProjectsResponse.java | 36 ++++++ .../v2/VersionFamilyBuildsResponse.java | 89 +++++++++++++ .../response/v2/VersionFamilyResponse.java | 49 ++++++++ .../api/response/v2/VersionResponse.java | 49 ++++++++ .../LegacyChannelSerializer.java | 19 +++ .../controller/v2/DownloadController.java | 25 ++-- .../controller/v2/ProjectController.java | 41 ++---- .../controller/v2/ProjectsController.java | 19 +-- .../controller/v2/VersionBuildController.java | 68 +++------- .../v2/VersionBuildsController.java | 78 ++++-------- .../controller/v2/VersionController.java | 45 +++---- .../v2/VersionFamilyBuildsController.java | 94 ++++---------- .../v2/VersionFamilyController.java | 45 +++---- .../model/{Build.java => BuildEntity.java} | 119 +++++++++++------- .../{VersionFamily.java => FamilyEntity.java} | 46 +++++-- .../{Project.java => ProjectEntity.java} | 32 ++++- .../{Version.java => VersionEntity.java} | 55 ++++++-- .../database/repository/BuildCollection.java | 12 +- .../repository/ProjectCollection.java | 6 +- .../repository/VersionCollection.java | 12 +- .../repository/VersionFamilyCollection.java | 9 +- .../papermc/bibliothek/util/MediaTypes.java | 1 - 28 files changed, 890 insertions(+), 366 deletions(-) create mode 100644 src/main/java/io/papermc/bibliothek/api/model/Change.java create mode 100644 src/main/java/io/papermc/bibliothek/api/model/Channel.java create mode 100644 src/main/java/io/papermc/bibliothek/api/model/Download.java create mode 100644 src/main/java/io/papermc/bibliothek/api/response/v2/BuildResponse.java create mode 100644 src/main/java/io/papermc/bibliothek/api/response/v2/BuildsResponse.java create mode 100644 src/main/java/io/papermc/bibliothek/api/response/v2/ProjectResponse.java create mode 100644 src/main/java/io/papermc/bibliothek/api/response/v2/ProjectsResponse.java create mode 100644 src/main/java/io/papermc/bibliothek/api/response/v2/VersionFamilyBuildsResponse.java create mode 100644 src/main/java/io/papermc/bibliothek/api/response/v2/VersionFamilyResponse.java create mode 100644 src/main/java/io/papermc/bibliothek/api/response/v2/VersionResponse.java create mode 100644 src/main/java/io/papermc/bibliothek/api/serialization/LegacyChannelSerializer.java rename src/main/java/io/papermc/bibliothek/database/model/{Build.java => BuildEntity.java} (57%) rename src/main/java/io/papermc/bibliothek/database/model/{VersionFamily.java => FamilyEntity.java} (69%) rename src/main/java/io/papermc/bibliothek/database/model/{Project.java => ProjectEntity.java} (77%) rename src/main/java/io/papermc/bibliothek/database/model/{Version.java => VersionEntity.java} (69%) diff --git a/src/main/java/io/papermc/bibliothek/api/model/Change.java b/src/main/java/io/papermc/bibliothek/api/model/Change.java new file mode 100644 index 0000000..eb19514 --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/model/Change.java @@ -0,0 +1,37 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.model; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema +public record Change( + @Schema(name = "commit") + String commit, + @Schema(name = "summary") + String summary, + @Schema(name = "message") + String message +) { +} diff --git a/src/main/java/io/papermc/bibliothek/api/model/Channel.java b/src/main/java/io/papermc/bibliothek/api/model/Channel.java new file mode 100644 index 0000000..f775a86 --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/model/Channel.java @@ -0,0 +1,29 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.model; + +public enum Channel { + DEFAULT, + EXPERIMENTAL; +} diff --git a/src/main/java/io/papermc/bibliothek/api/model/Download.java b/src/main/java/io/papermc/bibliothek/api/model/Download.java new file mode 100644 index 0000000..87b0832 --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/model/Download.java @@ -0,0 +1,35 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.model; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema +public record Download( + @Schema(name = "name", pattern = "[a-z0-9._-]+", example = "paper-1.18-10.jar") + String name, + @Schema(name = "sha256", pattern = "[a-f0-9]{64}", example = "f065e2d345d9d772d5cf2a1ce5c495c4cc56eb2fcd6820e82856485fa19414c8") + String sha256 +) { +} diff --git a/src/main/java/io/papermc/bibliothek/api/response/v2/BuildResponse.java b/src/main/java/io/papermc/bibliothek/api/response/v2/BuildResponse.java new file mode 100644 index 0000000..370977c --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/response/v2/BuildResponse.java @@ -0,0 +1,77 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.response.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.papermc.bibliothek.api.model.Change; +import io.papermc.bibliothek.api.model.Channel; +import io.papermc.bibliothek.api.model.Download; +import io.papermc.bibliothek.api.serialization.LegacyChannelSerializer; +import io.papermc.bibliothek.database.model.VersionEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.Instant; +import java.util.List; +import java.util.Map; + +@Schema +public record BuildResponse( + @JsonProperty("project_id") + @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") + String projectId, + + @JsonProperty("project_name") + @Schema(name = "project_name", example = "Paper") + String projectName, + + @JsonProperty("version") + @Schema(name = "version", pattern = VersionEntity.PATTERN, example = "1.18") + String version, + + @JsonProperty("build") + @Schema(name = "build", pattern = "\\d+", example = "10") + int build, + + @JsonProperty("time") + @Schema(name = "time") + Instant time, + + @JsonProperty("channel") + @JsonSerialize(using = LegacyChannelSerializer.class) + @Schema(name = "channel") + Channel channel, + + @JsonProperty("promoted") + @Schema(name = "promoted") + boolean promoted, + + @JsonProperty("changes") + @Schema(name = "changes") + List changes, + + @JsonProperty("downloads") + @Schema(name = "downloads") + Map downloads +) { +} diff --git a/src/main/java/io/papermc/bibliothek/api/response/v2/BuildsResponse.java b/src/main/java/io/papermc/bibliothek/api/response/v2/BuildsResponse.java new file mode 100644 index 0000000..c83da06 --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/response/v2/BuildsResponse.java @@ -0,0 +1,81 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.response.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.papermc.bibliothek.api.model.Change; +import io.papermc.bibliothek.api.model.Channel; +import io.papermc.bibliothek.api.model.Download; +import io.papermc.bibliothek.database.model.VersionEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.Instant; +import java.util.List; +import java.util.Map; + +@Schema +public record BuildsResponse( + @JsonProperty("project_id") + @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") + String projectId, + + @JsonProperty("project_name") + @Schema(name = "project_name", example = "Paper") + String projectName, + + @JsonProperty("version") + @Schema(name = "version", pattern = VersionEntity.PATTERN, example = "1.18") + String version, + + @JsonProperty("builds") + @Schema(name = "builds") + List builds +) { + @Schema + public record VersionBuild( + @JsonProperty("build") + @Schema(name = "build", pattern = "\\d+", example = "10") + int build, + + @JsonProperty("time") + @Schema(name = "time") + Instant time, + + @JsonProperty("channel") + @Schema(name = "channel") + Channel channel, + + @JsonProperty("promoted") + @Schema(name = "promoted") + boolean promoted, + + @JsonProperty("changes") + @Schema(name = "changes") + List changes, + + @JsonProperty("downloads") + @Schema(name = "downloads") + Map downloads + ) { + } +} diff --git a/src/main/java/io/papermc/bibliothek/api/response/v2/ProjectResponse.java b/src/main/java/io/papermc/bibliothek/api/response/v2/ProjectResponse.java new file mode 100644 index 0000000..6f0b00e --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/response/v2/ProjectResponse.java @@ -0,0 +1,48 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.response.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + +@Schema +public record ProjectResponse( + @JsonProperty("project_id") + @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") + String projectId, + + @JsonProperty("project_name") + @Schema(name = "project_name", example = "Paper") + String projectName, + + @JsonProperty("version_groups") + @Schema(name = "version_groups") + List versionGroups, + + @JsonProperty("versions") + @Schema(name = "versions") + List versions +) { +} diff --git a/src/main/java/io/papermc/bibliothek/api/response/v2/ProjectsResponse.java b/src/main/java/io/papermc/bibliothek/api/response/v2/ProjectsResponse.java new file mode 100644 index 0000000..0a9a07c --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/response/v2/ProjectsResponse.java @@ -0,0 +1,36 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.response.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + +@Schema +public record ProjectsResponse( + @JsonProperty("projects") + @Schema(name = "projects") + List projects +) { +} diff --git a/src/main/java/io/papermc/bibliothek/api/response/v2/VersionFamilyBuildsResponse.java b/src/main/java/io/papermc/bibliothek/api/response/v2/VersionFamilyBuildsResponse.java new file mode 100644 index 0000000..9d04992 --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/response/v2/VersionFamilyBuildsResponse.java @@ -0,0 +1,89 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.response.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.papermc.bibliothek.api.model.Change; +import io.papermc.bibliothek.api.model.Channel; +import io.papermc.bibliothek.api.model.Download; +import io.papermc.bibliothek.database.model.VersionEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.Instant; +import java.util.List; +import java.util.Map; + +@Schema +public record VersionFamilyBuildsResponse( + @JsonProperty("project_id") + @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") + String projectId, + + @JsonProperty("project_name") + @Schema(name = "project_name", example = "Paper") + String projectName, + + @JsonProperty("version_group") + @Schema(name = "version_group", pattern = VersionEntity.PATTERN, example = "1.18") + String versionGroup, + + @JsonProperty("versions") + @Schema(name = "versions") + List versions, + + @JsonProperty("builds") + @Schema(name = "builds") + List builds +) { + @Schema + public record VersionFamilyBuild( + @JsonProperty("version") + @Schema(name = "version", pattern = VersionEntity.PATTERN, example = "1.18") + String version, + + @JsonProperty("build") + @Schema(name = "build", pattern = "\\d+", example = "10") + int build, + + @JsonProperty("time") + @Schema(name = "time") + Instant time, + + @JsonProperty("channel") + @Schema(name = "channel") + Channel channel, + + @JsonProperty("promoted") + @Schema(name = "promoted") + boolean promoted, + + @JsonProperty("changes") + @Schema(name = "changes") + List changes, + + @JsonProperty("downloads") + @Schema(name = "downloads") + Map downloads + ) { + } +} diff --git a/src/main/java/io/papermc/bibliothek/api/response/v2/VersionFamilyResponse.java b/src/main/java/io/papermc/bibliothek/api/response/v2/VersionFamilyResponse.java new file mode 100644 index 0000000..a20cec9 --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/response/v2/VersionFamilyResponse.java @@ -0,0 +1,49 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.response.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.papermc.bibliothek.database.model.VersionEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + +@Schema +public record VersionFamilyResponse( + @JsonProperty("project_id") + @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") + String projectId, + + @JsonProperty("project_name") + @Schema(name = "project_name", example = "Paper") + String projectName, + + @JsonProperty("version_group") + @Schema(name = "version_group", pattern = VersionEntity.PATTERN, example = "1.18") + String versionGroup, + + @JsonProperty("versions") + @Schema(name = "versions") + List versions +) { +} diff --git a/src/main/java/io/papermc/bibliothek/api/response/v2/VersionResponse.java b/src/main/java/io/papermc/bibliothek/api/response/v2/VersionResponse.java new file mode 100644 index 0000000..b4eeab2 --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/response/v2/VersionResponse.java @@ -0,0 +1,49 @@ +/* + * This file is part of bibliothek, licensed under the MIT License. + * + * Copyright (c) 2019-2024 PaperMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.papermc.bibliothek.api.response.v2; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.papermc.bibliothek.database.model.VersionEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + +@Schema +public record VersionResponse( + @JsonProperty("project_id") + @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") + String projectId, + + @JsonProperty("project_name") + @Schema(name = "project_name", example = "Paper") + String projectName, + + @JsonProperty("version") + @Schema(name = "version", pattern = VersionEntity.PATTERN, example = "1.18") + String version, + + @JsonProperty("builds") + @Schema(name = "builds") + List builds +) { +} diff --git a/src/main/java/io/papermc/bibliothek/api/serialization/LegacyChannelSerializer.java b/src/main/java/io/papermc/bibliothek/api/serialization/LegacyChannelSerializer.java new file mode 100644 index 0000000..352844b --- /dev/null +++ b/src/main/java/io/papermc/bibliothek/api/serialization/LegacyChannelSerializer.java @@ -0,0 +1,19 @@ +package io.papermc.bibliothek.api.serialization; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import io.papermc.bibliothek.api.model.Channel; +import java.io.IOException; +import java.util.Locale; + +public class LegacyChannelSerializer extends StdSerializer { + public LegacyChannelSerializer() { + super(Channel.class); + } + + @Override + public void serialize(final Channel value, final JsonGenerator gen, final SerializerProvider provider) throws IOException { + gen.writeString(value.name().toLowerCase(Locale.ROOT)); + } +} diff --git a/src/main/java/io/papermc/bibliothek/controller/v2/DownloadController.java b/src/main/java/io/papermc/bibliothek/controller/v2/DownloadController.java index ea016f2..504a778 100644 --- a/src/main/java/io/papermc/bibliothek/controller/v2/DownloadController.java +++ b/src/main/java/io/papermc/bibliothek/controller/v2/DownloadController.java @@ -23,10 +23,11 @@ */ package io.papermc.bibliothek.controller.v2; +import io.papermc.bibliothek.api.model.Download; import io.papermc.bibliothek.configuration.AppConfiguration; -import io.papermc.bibliothek.database.model.Build; -import io.papermc.bibliothek.database.model.Project; -import io.papermc.bibliothek.database.model.Version; +import io.papermc.bibliothek.database.model.BuildEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; +import io.papermc.bibliothek.database.model.VersionEntity; import io.papermc.bibliothek.database.repository.BuildCollection; import io.papermc.bibliothek.database.repository.ProjectCollection; import io.papermc.bibliothek.database.repository.VersionCollection; @@ -49,6 +50,7 @@ import java.nio.file.Path; import java.time.Duration; import java.util.Map; +import org.intellij.lang.annotations.Language; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.FileSystemResource; import org.springframework.http.CacheControl; @@ -65,6 +67,9 @@ @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE) @SuppressWarnings("checkstyle:FinalClass") public class DownloadController { + // NOTE: this pattern cannot contain any capturing groups + @Language("RegExp") + private static final String DOWNLOAD_NAME_PATTERN = "[a-zA-Z0-9._-]+"; private static final CacheControl CACHE = HTTP.sMaxAgePublicCache(Duration.ofDays(7)); private final AppConfiguration configuration; private final ProjectCollection projects; @@ -105,7 +110,7 @@ private DownloadController( } ) @GetMapping( - value = "/v2/projects/{project:[a-z]+}/versions/{version:" + Version.PATTERN + "}/builds/{build:\\d+}/downloads/{download:" + Build.Download.PATTERN + "}", + value = "/v2/projects/{project:[a-z]+}/versions/{version:" + VersionEntity.PATTERN + "}/builds/{build:\\d+}/downloads/{download:" + DOWNLOAD_NAME_PATTERN + "}", produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.ALL_VALUE @@ -119,7 +124,7 @@ public ResponseEntity download( final String projectName, @Parameter(description = "A version of the project.") @PathVariable("version") - @Pattern(regexp = Version.PATTERN) // + @Pattern(regexp = VersionEntity.PATTERN) // final String versionName, @Parameter(description = "A build of the version.") @PathVariable("build") @@ -127,14 +132,14 @@ public ResponseEntity download( final int buildNumber, @Parameter(description = "A download of the build.") @PathVariable("download") - @Pattern(regexp = Build.Download.PATTERN) // + @Pattern(regexp = DOWNLOAD_NAME_PATTERN) // final String downloadName ) { - final Project project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); - final Version version = this.versions.findByProjectAndName(project._id(), versionName).orElseThrow(VersionNotFound::new); - final Build build = this.builds.findByProjectAndVersionAndNumber(project._id(), version._id(), buildNumber).orElseThrow(BuildNotFound::new); + final ProjectEntity project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); + final VersionEntity version = this.versions.findByProjectAndName(project, versionName).orElseThrow(VersionNotFound::new); + final BuildEntity build = this.builds.findByProjectAndVersionAndNumber(project, version, buildNumber).orElseThrow(BuildNotFound::new); - for (final Map.Entry download : build.downloads().entrySet()) { + for (final Map.Entry download : build.downloads().entrySet()) { if (download.getValue().name().equals(downloadName)) { try { return new JavaArchive( diff --git a/src/main/java/io/papermc/bibliothek/controller/v2/ProjectController.java b/src/main/java/io/papermc/bibliothek/controller/v2/ProjectController.java index 6109315..52860b7 100644 --- a/src/main/java/io/papermc/bibliothek/controller/v2/ProjectController.java +++ b/src/main/java/io/papermc/bibliothek/controller/v2/ProjectController.java @@ -23,9 +23,10 @@ */ package io.papermc.bibliothek.controller.v2; -import io.papermc.bibliothek.database.model.Project; -import io.papermc.bibliothek.database.model.Version; -import io.papermc.bibliothek.database.model.VersionFamily; +import io.papermc.bibliothek.api.response.v2.ProjectResponse; +import io.papermc.bibliothek.database.model.FamilyEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; +import io.papermc.bibliothek.database.model.VersionEntity; import io.papermc.bibliothek.database.repository.ProjectCollection; import io.papermc.bibliothek.database.repository.VersionCollection; import io.papermc.bibliothek.database.repository.VersionFamilyCollection; @@ -82,30 +83,14 @@ public ResponseEntity project( @Pattern(regexp = "[a-z]+") // final String projectName ) { - final Project project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); - final List families = this.families.findAllByProject(project._id()); - final List versions = this.versions.findAllByProject(project._id()); - return HTTP.cachedOk(ProjectResponse.from(project, families, versions), CACHE); - } - - @Schema - private record ProjectResponse( - @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") - String project_id, - @Schema(name = "project_name", example = "Paper") - String project_name, - @Schema(name = "version_groups") - List version_groups, - @Schema(name = "versions") - List versions - ) { - static ProjectResponse from(final Project project, final List families, final List versions) { - return new ProjectResponse( - project.name(), - project.friendlyName(), - families.stream().sorted(VersionFamily.COMPARATOR).map(VersionFamily::name).toList(), - versions.stream().sorted(Version.COMPARATOR).map(Version::name).toList() - ); - } + final ProjectEntity project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); + final List families = this.families.findAllByProject(project); + final List versions = this.versions.findAllByProject(project); + return HTTP.cachedOk(new ProjectResponse( + project.name(), + project.friendlyName(), + families.stream().sorted(FamilyEntity.COMPARATOR).map(FamilyEntity::name).toList(), + versions.stream().sorted(VersionEntity.COMPARATOR).map(VersionEntity::name).toList() + ), CACHE); } } diff --git a/src/main/java/io/papermc/bibliothek/controller/v2/ProjectsController.java b/src/main/java/io/papermc/bibliothek/controller/v2/ProjectsController.java index 16e176e..ef8d8f4 100644 --- a/src/main/java/io/papermc/bibliothek/controller/v2/ProjectsController.java +++ b/src/main/java/io/papermc/bibliothek/controller/v2/ProjectsController.java @@ -23,7 +23,8 @@ */ package io.papermc.bibliothek.controller.v2; -import io.papermc.bibliothek.database.model.Project; +import io.papermc.bibliothek.api.response.v2.ProjectsResponse; +import io.papermc.bibliothek.database.model.ProjectEntity; import io.papermc.bibliothek.database.repository.ProjectCollection; import io.papermc.bibliothek.util.HTTP; import io.swagger.v3.oas.annotations.Operation; @@ -61,17 +62,9 @@ private ProjectsController(final ProjectCollection projects) { @GetMapping("/v2/projects") @Operation(summary = "Gets a list of all available projects.") public ResponseEntity projects() { - final List projects = this.projects.findAll(); - return HTTP.cachedOk(ProjectsResponse.from(projects), CACHE); - } - - @Schema - private record ProjectsResponse( - @Schema(name = "projects") - List projects - ) { - static ProjectsResponse from(final List projects) { - return new ProjectsResponse(projects.stream().map(Project::name).toList()); - } + final List projects = this.projects.findAll(); + return HTTP.cachedOk(new ProjectsResponse( + projects.stream().map(ProjectEntity::name).toList() + ), CACHE); } } diff --git a/src/main/java/io/papermc/bibliothek/controller/v2/VersionBuildController.java b/src/main/java/io/papermc/bibliothek/controller/v2/VersionBuildController.java index 1152e66..e0e94f8 100644 --- a/src/main/java/io/papermc/bibliothek/controller/v2/VersionBuildController.java +++ b/src/main/java/io/papermc/bibliothek/controller/v2/VersionBuildController.java @@ -23,9 +23,10 @@ */ package io.papermc.bibliothek.controller.v2; -import io.papermc.bibliothek.database.model.Build; -import io.papermc.bibliothek.database.model.Project; -import io.papermc.bibliothek.database.model.Version; +import io.papermc.bibliothek.api.response.v2.BuildResponse; +import io.papermc.bibliothek.database.model.BuildEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; +import io.papermc.bibliothek.database.model.VersionEntity; import io.papermc.bibliothek.database.repository.BuildCollection; import io.papermc.bibliothek.database.repository.ProjectCollection; import io.papermc.bibliothek.database.repository.VersionCollection; @@ -41,9 +42,6 @@ import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Positive; import java.time.Duration; -import java.time.Instant; -import java.util.List; -import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.CacheControl; import org.springframework.http.MediaType; @@ -79,7 +77,7 @@ private VersionBuildController( ), responseCode = "200" ) - @GetMapping("/v2/projects/{project:[a-z]+}/versions/{version:" + Version.PATTERN + "}/builds/{build:\\d+}") + @GetMapping("/v2/projects/{project:[a-z]+}/versions/{version:" + VersionEntity.PATTERN + "}/builds/{build:\\d+}") @Operation(summary = "Gets information related to a specific build.") public ResponseEntity build( @Parameter(name = "project", description = "The project identifier.", example = "paper") @@ -88,52 +86,26 @@ public ResponseEntity build( final String projectName, @Parameter(description = "A version of the project.") @PathVariable("version") - @Pattern(regexp = Version.PATTERN) // + @Pattern(regexp = VersionEntity.PATTERN) // final String versionName, @Parameter(description = "A build of the version.") @PathVariable("build") @Positive // final int buildNumber ) { - final Project project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); - final Version version = this.versions.findByProjectAndName(project._id(), versionName).orElseThrow(VersionNotFound::new); - final Build build = this.builds.findByProjectAndVersionAndNumber(project._id(), version._id(), buildNumber).orElseThrow(BuildNotFound::new); - return HTTP.cachedOk(BuildResponse.from(project, version, build), CACHE); - } - - @Schema - private record BuildResponse( - @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") - String project_id, - @Schema(name = "project_name", example = "Paper") - String project_name, - @Schema(name = "version", pattern = Version.PATTERN, example = "1.18") - String version, - @Schema(name = "build", pattern = "\\d+", example = "10") - int build, - @Schema(name = "time") - Instant time, - @Schema(name = "channel") - Build.Channel channel, - @Schema(name = "promoted") - boolean promoted, - @Schema(name = "changes") - List changes, - @Schema(name = "downloads") - Map downloads - ) { - static BuildResponse from(final Project project, final Version version, final Build build) { - return new BuildResponse( - project.name(), - project.friendlyName(), - version.name(), - build.number(), - build.time(), - build.channelOrDefault(), - build.promotedOrDefault(), - build.changes(), - build.downloads() - ); - } + final ProjectEntity project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); + final VersionEntity version = this.versions.findByProjectAndName(project, versionName).orElseThrow(VersionNotFound::new); + final BuildEntity build = this.builds.findByProjectAndVersionAndNumber(project, version, buildNumber).orElseThrow(BuildNotFound::new); + return HTTP.cachedOk(new BuildResponse( + project.name(), + project.friendlyName(), + version.name(), + build.number(), + build.time(), + build.channelOrDefault(), + build.promotedOrDefault(), + build.changes(), + build.downloads() + ), CACHE); } } diff --git a/src/main/java/io/papermc/bibliothek/controller/v2/VersionBuildsController.java b/src/main/java/io/papermc/bibliothek/controller/v2/VersionBuildsController.java index 7dd879f..fc57eb0 100644 --- a/src/main/java/io/papermc/bibliothek/controller/v2/VersionBuildsController.java +++ b/src/main/java/io/papermc/bibliothek/controller/v2/VersionBuildsController.java @@ -23,9 +23,10 @@ */ package io.papermc.bibliothek.controller.v2; -import io.papermc.bibliothek.database.model.Build; -import io.papermc.bibliothek.database.model.Project; -import io.papermc.bibliothek.database.model.Version; +import io.papermc.bibliothek.api.response.v2.BuildsResponse; +import io.papermc.bibliothek.database.model.BuildEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; +import io.papermc.bibliothek.database.model.VersionEntity; import io.papermc.bibliothek.database.repository.BuildCollection; import io.papermc.bibliothek.database.repository.ProjectCollection; import io.papermc.bibliothek.database.repository.VersionCollection; @@ -39,9 +40,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import jakarta.validation.constraints.Pattern; import java.time.Duration; -import java.time.Instant; import java.util.List; -import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.CacheControl; import org.springframework.http.MediaType; @@ -77,7 +76,7 @@ private VersionBuildsController( ), responseCode = "200" ) - @GetMapping("/v2/projects/{project:[a-z]+}/versions/{version:" + Version.PATTERN + "}/builds") + @GetMapping("/v2/projects/{project:[a-z]+}/versions/{version:" + VersionEntity.PATTERN + "}/builds") @Operation(summary = "Gets all available builds for a project's version.") public ResponseEntity builds( @Parameter(name = "project", description = "The project identifier.", example = "paper") @@ -86,57 +85,24 @@ public ResponseEntity builds( final String projectName, @Parameter(description = "A version of the project.") @PathVariable("version") - @Pattern(regexp = Version.PATTERN) // + @Pattern(regexp = VersionEntity.PATTERN) // final String versionName ) { - final Project project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); - final Version version = this.versions.findByProjectAndName(project._id(), versionName).orElseThrow(VersionNotFound::new); - final List builds = this.builds.findAllByProjectAndVersion(project._id(), version._id()); - return HTTP.cachedOk(BuildsResponse.from(project, version, builds), CACHE); - } - - @Schema - private record BuildsResponse( - @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") - String project_id, - @Schema(name = "project_name", example = "Paper") - String project_name, - @Schema(name = "version", pattern = Version.PATTERN, example = "1.18") - String version, - @Schema(name = "builds") - List builds - ) { - static BuildsResponse from(final Project project, final Version version, final List builds) { - return new BuildsResponse( - project.name(), - project.friendlyName(), - version.name(), - builds.stream().map(build -> new VersionBuild( - build.number(), - build.time(), - build.channelOrDefault(), - build.promotedOrDefault(), - build.changes(), - build.downloads() - )).toList() - ); - } - - @Schema - public record VersionBuild( - @Schema(name = "build", pattern = "\\d+", example = "10") - int build, - @Schema(name = "time") - Instant time, - @Schema(name = "channel") - Build.Channel channel, - @Schema(name = "promoted") - boolean promoted, - @Schema(name = "changes") - List changes, - @Schema(name = "downloads") - Map downloads - ) { - } + final ProjectEntity project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); + final VersionEntity version = this.versions.findByProjectAndName(project, versionName).orElseThrow(VersionNotFound::new); + final List builds = this.builds.findAllByProjectAndVersion(project, version); + return HTTP.cachedOk(new BuildsResponse( + project.name(), + project.friendlyName(), + version.name(), + builds.stream().map(build -> new BuildsResponse.VersionBuild( + build.number(), + build.time(), + build.channelOrDefault(), + build.promotedOrDefault(), + build.changes(), + build.downloads() + )).toList() + ), CACHE); } } diff --git a/src/main/java/io/papermc/bibliothek/controller/v2/VersionController.java b/src/main/java/io/papermc/bibliothek/controller/v2/VersionController.java index 93bf72d..ebb000d 100644 --- a/src/main/java/io/papermc/bibliothek/controller/v2/VersionController.java +++ b/src/main/java/io/papermc/bibliothek/controller/v2/VersionController.java @@ -23,9 +23,10 @@ */ package io.papermc.bibliothek.controller.v2; -import io.papermc.bibliothek.database.model.Build; -import io.papermc.bibliothek.database.model.Project; -import io.papermc.bibliothek.database.model.Version; +import io.papermc.bibliothek.api.response.v2.VersionResponse; +import io.papermc.bibliothek.database.model.BuildEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; +import io.papermc.bibliothek.database.model.VersionEntity; import io.papermc.bibliothek.database.repository.BuildCollection; import io.papermc.bibliothek.database.repository.ProjectCollection; import io.papermc.bibliothek.database.repository.VersionCollection; @@ -75,7 +76,7 @@ private VersionController( ), responseCode = "200" ) - @GetMapping("/v2/projects/{project:[a-z]+}/versions/{version:" + Version.PATTERN + "}") + @GetMapping("/v2/projects/{project:[a-z]+}/versions/{version:" + VersionEntity.PATTERN + "}") @Operation(summary = "Gets information about a version.") public ResponseEntity version( @Parameter(name = "project", description = "The project identifier.", example = "paper") @@ -84,33 +85,17 @@ public ResponseEntity version( final String projectName, @Parameter(description = "A version of the project.") @PathVariable("version") - @Pattern(regexp = Version.PATTERN) // + @Pattern(regexp = VersionEntity.PATTERN) // final String versionName ) { - final Project project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); - final Version version = this.versions.findByProjectAndName(project._id(), versionName).orElseThrow(VersionNotFound::new); - final List builds = this.builds.findAllByProjectAndVersion(project._id(), version._id()); - return HTTP.cachedOk(VersionResponse.from(project, version, builds), CACHE); - } - - @Schema - private record VersionResponse( - @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") - String project_id, - @Schema(name = "project_name", example = "Paper") - String project_name, - @Schema(name = "version", pattern = Version.PATTERN, example = "1.18") - String version, - @Schema(name = "builds") - List builds - ) { - static VersionResponse from(final Project project, final Version version, final List builds) { - return new VersionResponse( - project.name(), - project.friendlyName(), - version.name(), - builds.stream().map(Build::number).toList() - ); - } + final ProjectEntity project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); + final VersionEntity version = this.versions.findByProjectAndName(project, versionName).orElseThrow(VersionNotFound::new); + final List builds = this.builds.findAllByProjectAndVersion(project, version); + return HTTP.cachedOk(new VersionResponse( + project.name(), + project.friendlyName(), + version.name(), + builds.stream().map(BuildEntity::number).toList() + ), CACHE); } } diff --git a/src/main/java/io/papermc/bibliothek/controller/v2/VersionFamilyBuildsController.java b/src/main/java/io/papermc/bibliothek/controller/v2/VersionFamilyBuildsController.java index 63b1e16..ec07691 100644 --- a/src/main/java/io/papermc/bibliothek/controller/v2/VersionFamilyBuildsController.java +++ b/src/main/java/io/papermc/bibliothek/controller/v2/VersionFamilyBuildsController.java @@ -23,10 +23,11 @@ */ package io.papermc.bibliothek.controller.v2; -import io.papermc.bibliothek.database.model.Build; -import io.papermc.bibliothek.database.model.Project; -import io.papermc.bibliothek.database.model.Version; -import io.papermc.bibliothek.database.model.VersionFamily; +import io.papermc.bibliothek.api.response.v2.VersionFamilyBuildsResponse; +import io.papermc.bibliothek.database.model.BuildEntity; +import io.papermc.bibliothek.database.model.FamilyEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; +import io.papermc.bibliothek.database.model.VersionEntity; import io.papermc.bibliothek.database.repository.BuildCollection; import io.papermc.bibliothek.database.repository.ProjectCollection; import io.papermc.bibliothek.database.repository.VersionCollection; @@ -41,12 +42,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import jakarta.validation.constraints.Pattern; import java.time.Duration; -import java.time.Instant; import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.CacheControl; import org.springframework.http.MediaType; @@ -85,7 +81,7 @@ private VersionFamilyBuildsController( ), responseCode = "200" ) - @GetMapping("/v2/projects/{project:[a-z]+}/version_group/{family:" + Version.PATTERN + "}/builds") + @GetMapping("/v2/projects/{project:[a-z]+}/version_group/{family:" + VersionEntity.PATTERN + "}/builds") @Operation(summary = "Gets all available builds for a project's version group.") public ResponseEntity familyBuilds( @Parameter(name = "project", description = "The project identifier.", example = "paper") @@ -94,65 +90,27 @@ public ResponseEntity familyBuilds( final String projectName, @Parameter(description = "The version group name.") @PathVariable("family") - @Pattern(regexp = Version.PATTERN) // + @Pattern(regexp = VersionEntity.PATTERN) // final String familyName ) { - final Project project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); - final VersionFamily family = this.families.findByProjectAndName(project._id(), familyName).orElseThrow(VersionNotFound::new); - final Map versions = this.versions.findAllByProjectAndGroup(project._id(), family._id()).stream() - .collect(Collectors.toMap(Version::_id, Function.identity())); - final List builds = this.builds.findAllByProjectAndVersionIn(project._id(), versions.keySet()); - return HTTP.cachedOk(VersionFamilyBuildsResponse.from(project, family, versions, builds), CACHE); - } - - @Schema - private record VersionFamilyBuildsResponse( - @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") - String project_id, - @Schema(name = "project_name", example = "Paper") - String project_name, - @Schema(name = "version_group", pattern = Version.PATTERN, example = "1.18") - String version_group, - @Schema(name = "versions") - List versions, - @Schema(name = "builds") - List builds - ) { - static VersionFamilyBuildsResponse from(final Project project, final VersionFamily family, final Map versions, final List builds) { - return new VersionFamilyBuildsResponse( - project.name(), - project.friendlyName(), - family.name(), - versions.values().stream().sorted(Version.COMPARATOR).map(Version::name).toList(), - builds.stream().map(build -> new VersionFamilyBuild( - versions.get(build.version()).name(), - build.number(), - build.time(), - build.channelOrDefault(), - build.promotedOrDefault(), - build.changes(), - build.downloads() - )).toList() - ); - } - - @Schema - public static record VersionFamilyBuild( - @Schema(name = "version", pattern = Version.PATTERN, example = "1.18") - String version, - @Schema(name = "build", pattern = "\\d+", example = "10") - int build, - @Schema(name = "time") - Instant time, - @Schema(name = "channel") - Build.Channel channel, - @Schema(name = "promoted") - boolean promoted, - @Schema(name = "changes") - List changes, - @Schema(name = "downloads") - Map downloads - ) { - } + final ProjectEntity project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); + final FamilyEntity family = this.families.findByProjectAndName(project, familyName).orElseThrow(VersionNotFound::new); + final List versions = this.versions.findAllByProjectAndGroup(project, family); + final List builds = this.builds.findAllByProjectAndVersionIn(project, versions); + return HTTP.cachedOk(new VersionFamilyBuildsResponse( + project.name(), + project.friendlyName(), + family.name(), + versions.stream().sorted(VersionEntity.COMPARATOR).map(VersionEntity::name).toList(), + builds.stream().map(build -> new VersionFamilyBuildsResponse.VersionFamilyBuild( + build.version().name(), + build.number(), + build.time(), + build.channelOrDefault(), + build.promotedOrDefault(), + build.changes(), + build.downloads() + )).toList() + ), CACHE); } } diff --git a/src/main/java/io/papermc/bibliothek/controller/v2/VersionFamilyController.java b/src/main/java/io/papermc/bibliothek/controller/v2/VersionFamilyController.java index 662d341..41ffe00 100644 --- a/src/main/java/io/papermc/bibliothek/controller/v2/VersionFamilyController.java +++ b/src/main/java/io/papermc/bibliothek/controller/v2/VersionFamilyController.java @@ -23,9 +23,10 @@ */ package io.papermc.bibliothek.controller.v2; -import io.papermc.bibliothek.database.model.Project; -import io.papermc.bibliothek.database.model.Version; -import io.papermc.bibliothek.database.model.VersionFamily; +import io.papermc.bibliothek.api.response.v2.VersionFamilyResponse; +import io.papermc.bibliothek.database.model.FamilyEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; +import io.papermc.bibliothek.database.model.VersionEntity; import io.papermc.bibliothek.database.repository.ProjectCollection; import io.papermc.bibliothek.database.repository.VersionCollection; import io.papermc.bibliothek.database.repository.VersionFamilyCollection; @@ -75,7 +76,7 @@ private VersionFamilyController( ), responseCode = "200" ) - @GetMapping("/v2/projects/{project:[a-z]+}/version_group/{family:" + Version.PATTERN + "}") + @GetMapping("/v2/projects/{project:[a-z]+}/version_group/{family:" + VersionEntity.PATTERN + "}") @Operation(summary = "Gets information about a project's version group.") public ResponseEntity family( @Parameter(name = "project", description = "The project identifier.", example = "paper") @@ -84,33 +85,17 @@ public ResponseEntity family( final String projectName, @Parameter(description = "The version group name.") @PathVariable("family") - @Pattern(regexp = Version.PATTERN) // + @Pattern(regexp = VersionEntity.PATTERN) // final String familyName ) { - final Project project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); - final VersionFamily family = this.families.findByProjectAndName(project._id(), familyName).orElseThrow(VersionNotFound::new); - final List versions = this.versions.findAllByProjectAndGroup(project._id(), family._id()); - return HTTP.cachedOk(VersionFamilyResponse.from(project, family, versions), CACHE); - } - - @Schema - private record VersionFamilyResponse( - @Schema(name = "project_id", pattern = "[a-z]+", example = "paper") - String project_id, - @Schema(name = "project_name", example = "Paper") - String project_name, - @Schema(name = "version_group", pattern = Version.PATTERN, example = "1.18") - String version_group, - @Schema(name = "versions") - List versions - ) { - static VersionFamilyResponse from(final Project project, final VersionFamily family, final List versions) { - return new VersionFamilyResponse( - project.name(), - project.friendlyName(), - family.name(), - versions.stream().sorted(Version.COMPARATOR).map(Version::name).toList() - ); - } + final ProjectEntity project = this.projects.findByName(projectName).orElseThrow(ProjectNotFound::new); + final FamilyEntity family = this.families.findByProjectAndName(project, familyName).orElseThrow(VersionNotFound::new); + final List versions = this.versions.findAllByProjectAndGroup(project, family); + return HTTP.cachedOk(new VersionFamilyResponse( + project.name(), + project.friendlyName(), + family.name(), + versions.stream().sorted(VersionEntity.COMPARATOR).map(VersionEntity::name).toList() + ), CACHE); } } diff --git a/src/main/java/io/papermc/bibliothek/database/model/Build.java b/src/main/java/io/papermc/bibliothek/database/model/BuildEntity.java similarity index 57% rename from src/main/java/io/papermc/bibliothek/database/model/Build.java rename to src/main/java/io/papermc/bibliothek/database/model/BuildEntity.java index efaaacf..b316c3c 100644 --- a/src/main/java/io/papermc/bibliothek/database/model/Build.java +++ b/src/main/java/io/papermc/bibliothek/database/model/BuildEntity.java @@ -23,71 +23,100 @@ */ package io.papermc.bibliothek.database.model; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.media.Schema; +import io.papermc.bibliothek.api.model.Change; +import io.papermc.bibliothek.api.model.Channel; +import io.papermc.bibliothek.api.model.Download; import java.time.Instant; import java.util.List; import java.util.Map; import java.util.Objects; import org.bson.types.ObjectId; -import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.Nullable; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.CompoundIndex; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.DocumentReference; +import org.springframework.data.mongodb.core.mapping.Field; @CompoundIndex(def = "{'project': 1, 'version': 1}") @CompoundIndex(def = "{'project': 1, 'version': 1, 'number': 1}") @Document(collection = "builds") -public record Build( - @Id ObjectId _id, - ObjectId project, - ObjectId version, - int number, - Instant time, - List changes, - Map downloads, - @JsonProperty - @Nullable Channel channel, - @JsonInclude(JsonInclude.Include.NON_NULL) - @Nullable Boolean promoted -) { - public Channel channelOrDefault() { - return Objects.requireNonNullElse(this.channel(), Build.Channel.DEFAULT); +public class BuildEntity { + @Field + @Id + private ObjectId _id; + + @DocumentReference + @Field + private ProjectEntity project; + + @DocumentReference + @Field + private VersionEntity version; + + @Field + private int number; + + @Field + private Instant time; + + @Field + private List changes; + + @Field + private Map downloads; + + @Field + private @Nullable Channel channel; + + @Field + private @Nullable Boolean promoted; + + public BuildEntity() { } - public boolean promotedOrDefault() { - return Objects.requireNonNullElse(this.promoted(), false); + @Id + public ObjectId _id() { + return this._id; } - public enum Channel { - @JsonProperty("default") - DEFAULT, - @JsonProperty("experimental") - EXPERIMENTAL; + public ProjectEntity project() { + return this.project; } - @Schema - public record Change( - @Schema(name = "commit") - String commit, - @Schema(name = "summary") - String summary, - @Schema(name = "message") - String message - ) { + public VersionEntity version() { + return this.version; } - @Schema - public record Download( - @Schema(name = "name", pattern = "[a-z0-9._-]+", example = "paper-1.18-10.jar") - String name, - @Schema(name = "sha256", pattern = "[a-f0-9]{64}", example = "f065e2d345d9d772d5cf2a1ce5c495c4cc56eb2fcd6820e82856485fa19414c8") - String sha256 - ) { - // NOTE: this pattern cannot contain any capturing groups - @Language("RegExp") - public static final String PATTERN = "[a-zA-Z0-9._-]+"; + public int number() { + return this.number; + } + + public Instant time() { + return this.time; + } + + public List changes() { + return this.changes; + } + + public Map downloads() { + return this.downloads; + } + + public @Nullable Channel channel() { + return this.channel; + } + + public Channel channelOrDefault() { + return Objects.requireNonNullElse(this.channel(), Channel.DEFAULT); + } + + public @Nullable Boolean promoted() { + return this.promoted; + } + + public boolean promotedOrDefault() { + return Objects.requireNonNullElse(this.promoted(), false); } } diff --git a/src/main/java/io/papermc/bibliothek/database/model/VersionFamily.java b/src/main/java/io/papermc/bibliothek/database/model/FamilyEntity.java similarity index 69% rename from src/main/java/io/papermc/bibliothek/database/model/VersionFamily.java rename to src/main/java/io/papermc/bibliothek/database/model/FamilyEntity.java index 2aadc71..6004dfe 100644 --- a/src/main/java/io/papermc/bibliothek/database/model/VersionFamily.java +++ b/src/main/java/io/papermc/bibliothek/database/model/FamilyEntity.java @@ -33,14 +33,46 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.CompoundIndex; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.DocumentReference; +import org.springframework.data.mongodb.core.mapping.Field; @CompoundIndex(def = "{'project': 1, 'name': 1}") @Document(collection = "version_groups") -public record VersionFamily( - @Id ObjectId _id, - ObjectId project, - String name, - @Nullable Instant time -) implements NameSource, TimeSource { - public static final Comparator COMPARATOR = BringOrderToChaos.timeOrNameComparator(); +public class FamilyEntity implements NameSource, TimeSource { + public static final Comparator COMPARATOR = BringOrderToChaos.timeOrNameComparator(); + + @Field + @Id + private ObjectId _id; + + @DocumentReference + @Field + private ProjectEntity project; + + @Field + private String name; + + @Field + private @Nullable Instant time; + + public FamilyEntity() { + } + + public ObjectId _id() { + return this._id; + } + + public ProjectEntity project() { + return this.project; + } + + @Override + public String name() { + return this.name; + } + + @Override + public @Nullable Instant time() { + return this.time; + } } diff --git a/src/main/java/io/papermc/bibliothek/database/model/Project.java b/src/main/java/io/papermc/bibliothek/database/model/ProjectEntity.java similarity index 77% rename from src/main/java/io/papermc/bibliothek/database/model/Project.java rename to src/main/java/io/papermc/bibliothek/database/model/ProjectEntity.java index 92a3f26..def2309 100644 --- a/src/main/java/io/papermc/bibliothek/database/model/Project.java +++ b/src/main/java/io/papermc/bibliothek/database/model/ProjectEntity.java @@ -27,11 +27,33 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; @Document(collection = "projects") -public record Project( - @Id ObjectId _id, - @Indexed String name, - String friendlyName -) { +public class ProjectEntity { + @Field + @Id + private ObjectId _id; + + @Field + @Indexed + private String name; + + @Field + private String friendlyName; + + public ProjectEntity() { + } + + public ObjectId _id() { + return this._id; + } + + public String name() { + return this.name; + } + + public String friendlyName() { + return this.friendlyName; + } } diff --git a/src/main/java/io/papermc/bibliothek/database/model/Version.java b/src/main/java/io/papermc/bibliothek/database/model/VersionEntity.java similarity index 69% rename from src/main/java/io/papermc/bibliothek/database/model/Version.java rename to src/main/java/io/papermc/bibliothek/database/model/VersionEntity.java index 8c6a5bd..31b1a66 100644 --- a/src/main/java/io/papermc/bibliothek/database/model/Version.java +++ b/src/main/java/io/papermc/bibliothek/database/model/VersionEntity.java @@ -34,19 +34,58 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.CompoundIndex; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.DocumentReference; +import org.springframework.data.mongodb.core.mapping.Field; @CompoundIndex(def = "{'project': 1, 'group': 1}") @CompoundIndex(def = "{'project': 1, 'name': 1}") @Document(collection = "versions") -public record Version( - @Id ObjectId _id, - ObjectId project, - ObjectId group, - String name, - @Nullable Instant time -) implements NameSource, TimeSource { +public class VersionEntity implements NameSource, TimeSource { // NOTE: this pattern cannot contain any capturing groups @Language("RegExp") public static final String PATTERN = "[0-9.]+-?(?:pre|SNAPSHOT)?(?:[0-9.]+)?"; - public static final Comparator COMPARATOR = BringOrderToChaos.timeOrNameComparator(); + public static final Comparator COMPARATOR = BringOrderToChaos.timeOrNameComparator(); + + @Field + @Id + private ObjectId _id; + + @DocumentReference + @Field + private ProjectEntity project; + + @DocumentReference + @Field + private FamilyEntity group; + + @Field + private String name; + + @Field + private @Nullable Instant time; + + public VersionEntity() { + } + + public ObjectId _id() { + return this._id; + } + + public ProjectEntity project() { + return this.project; + } + + public FamilyEntity group() { + return this.group; + } + + @Override + public String name() { + return this.name; + } + + @Override + public @Nullable Instant time() { + return this.time; + } } diff --git a/src/main/java/io/papermc/bibliothek/database/repository/BuildCollection.java b/src/main/java/io/papermc/bibliothek/database/repository/BuildCollection.java index 9e83935..73685aa 100644 --- a/src/main/java/io/papermc/bibliothek/database/repository/BuildCollection.java +++ b/src/main/java/io/papermc/bibliothek/database/repository/BuildCollection.java @@ -23,7 +23,9 @@ */ package io.papermc.bibliothek.database.repository; -import io.papermc.bibliothek.database.model.Build; +import io.papermc.bibliothek.database.model.BuildEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; +import io.papermc.bibliothek.database.model.VersionEntity; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -32,10 +34,10 @@ import org.springframework.stereotype.Repository; @Repository -public interface BuildCollection extends MongoRepository { - List findAllByProjectAndVersion(final ObjectId project, final ObjectId version); +public interface BuildCollection extends MongoRepository { + List findAllByProjectAndVersion(final ProjectEntity project, final VersionEntity version); - List findAllByProjectAndVersionIn(final ObjectId project, final Collection version); + List findAllByProjectAndVersionIn(final ProjectEntity project, final Collection version); - Optional findByProjectAndVersionAndNumber(final ObjectId project, final ObjectId version, final int number); + Optional findByProjectAndVersionAndNumber(final ProjectEntity project, final VersionEntity version, final int number); } diff --git a/src/main/java/io/papermc/bibliothek/database/repository/ProjectCollection.java b/src/main/java/io/papermc/bibliothek/database/repository/ProjectCollection.java index eb132d2..07ee95b 100644 --- a/src/main/java/io/papermc/bibliothek/database/repository/ProjectCollection.java +++ b/src/main/java/io/papermc/bibliothek/database/repository/ProjectCollection.java @@ -23,13 +23,13 @@ */ package io.papermc.bibliothek.database.repository; -import io.papermc.bibliothek.database.model.Project; +import io.papermc.bibliothek.database.model.ProjectEntity; import java.util.Optional; import org.bson.types.ObjectId; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; @Repository -public interface ProjectCollection extends MongoRepository { - Optional findByName(final String name); +public interface ProjectCollection extends MongoRepository { + Optional findByName(final String name); } diff --git a/src/main/java/io/papermc/bibliothek/database/repository/VersionCollection.java b/src/main/java/io/papermc/bibliothek/database/repository/VersionCollection.java index 6825fed..321a5cc 100644 --- a/src/main/java/io/papermc/bibliothek/database/repository/VersionCollection.java +++ b/src/main/java/io/papermc/bibliothek/database/repository/VersionCollection.java @@ -23,7 +23,9 @@ */ package io.papermc.bibliothek.database.repository; -import io.papermc.bibliothek.database.model.Version; +import io.papermc.bibliothek.database.model.FamilyEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; +import io.papermc.bibliothek.database.model.VersionEntity; import java.util.List; import java.util.Optional; import org.bson.types.ObjectId; @@ -31,10 +33,10 @@ import org.springframework.stereotype.Repository; @Repository -public interface VersionCollection extends MongoRepository { - List findAllByProject(final ObjectId project); +public interface VersionCollection extends MongoRepository { + List findAllByProject(final ProjectEntity project); - List findAllByProjectAndGroup(final ObjectId project, final ObjectId group); + List findAllByProjectAndGroup(final ProjectEntity project, final FamilyEntity group); - Optional findByProjectAndName(final ObjectId project, final String name); + Optional findByProjectAndName(final ProjectEntity project, final String name); } diff --git a/src/main/java/io/papermc/bibliothek/database/repository/VersionFamilyCollection.java b/src/main/java/io/papermc/bibliothek/database/repository/VersionFamilyCollection.java index f678f8d..e4b0d34 100644 --- a/src/main/java/io/papermc/bibliothek/database/repository/VersionFamilyCollection.java +++ b/src/main/java/io/papermc/bibliothek/database/repository/VersionFamilyCollection.java @@ -23,7 +23,8 @@ */ package io.papermc.bibliothek.database.repository; -import io.papermc.bibliothek.database.model.VersionFamily; +import io.papermc.bibliothek.database.model.FamilyEntity; +import io.papermc.bibliothek.database.model.ProjectEntity; import java.util.List; import java.util.Optional; import org.bson.types.ObjectId; @@ -31,8 +32,8 @@ import org.springframework.stereotype.Repository; @Repository -public interface VersionFamilyCollection extends MongoRepository { - List findAllByProject(final ObjectId project); +public interface VersionFamilyCollection extends MongoRepository { + List findAllByProject(final ProjectEntity project); - Optional findByProjectAndName(final ObjectId project, final String name); + Optional findByProjectAndName(final ProjectEntity project, final String name); } diff --git a/src/main/java/io/papermc/bibliothek/util/MediaTypes.java b/src/main/java/io/papermc/bibliothek/util/MediaTypes.java index ef04049..f6aca4b 100644 --- a/src/main/java/io/papermc/bibliothek/util/MediaTypes.java +++ b/src/main/java/io/papermc/bibliothek/util/MediaTypes.java @@ -28,7 +28,6 @@ import org.springframework.http.MediaTypeFactory; public final class MediaTypes { - public static final String APPLICATION_ZIP_VALUE = "application/zip"; public static final MediaType APPLICATION_ZIP = MediaType.parseMediaType(APPLICATION_ZIP_VALUE);