From 210a42c047dcdf0ff828b6f753cd9c9121e89511 Mon Sep 17 00:00:00 2001 From: Breno A Date: Thu, 11 Jan 2024 14:53:47 -0300 Subject: [PATCH 1/4] Delete .idea directory --- .idea/.gitignore | 8 -- .idea/checkstyle-idea.xml | 16 --- .idea/code-comments.xml | 6 - .idea/codeStyles/Project.xml | 7 - .idea/codeStyles/codeStyleConfig.xml | 5 - .idea/discord.xml | 7 - .idea/encodings.xml | 7 - .idea/inspectionProfiles/Project_Default.xml | 13 -- .idea/jpa-buddy.xml | 6 - .idea/misc.xml | 17 --- .../0305bb4613949c92aef5353c1d7a126b6e7579d8 | 0 .../0594be35c2451dc1dad1704a41e3aa7322049c02 | 0 .../0b6cca93c18fd28dfe71f15766b8dae8d1496f5d | 0 .../0f1021f3578e7ad2957e8b008e0bad3162cffa37 | 0 .../11df5582b58bf0be8bd720cf8b57086b5d420e2e | 0 .../17138a271f6b65f6e58ed5c925e5939061efa88b | 0 .../17d87d20633dc9ccd5afcf332b31a9db70d6d03b | 0 .../1b0c45eaf7c34d57e815c9d6ec2511aacd93e4e6 | 0 .../1f9ab227dacaf5f4df91653358b22843c4028842 | 0 .../219600aeaef7272327880879d76afa9a3a3803a9 | 0 .../234a46ce1d1da8058f0c7cff5b5d657bdb9368c2 | 5 - .../239ff22be2d75ead1a66ca1e121ff810d9e3ae44 | 0 .../2aade9ec44afbd161df0e408b132ab65c00f0b83 | 0 .../43e24e9dbb55ca782453bd914d361b5d3ada7565 | 0 .../4414d44f588a4ab11d5d0c32c69fdd579d4676cb | 0 .../442292b8a7efeabbe4cc176709b833b1792140ec | 0 .../48f80172f9f06882daf2a436c61d01615425490f | 0 .../4cc49a5ee72f18e86b67c29733dd5f0372aa72ea | 0 .../4dd037fec6dc7041b7ad1034deb31538dec04d54 | 0 .../53ab1377009a1c2afb7687753a40c1a282ed9a01 | 0 .../59dc694635ee875c1a489946d932ba89fb380489 | 0 .../5ac638408c94111e0c72f20a7f7109c7665ab1fa | 0 .../5d83a38896e5b0f4eb5e06e3db5cae5cc8471f07 | 0 .../5e0f556082b2c94ff4f99e1ce3e689554272895a | 0 .../62153552fd0bd9c00e0bdac387e64eb65d3eef7e | 0 .../65994bd67283a1d11002718d81b05f0eb8dd508e | 9 -- .../6760398c657563eebf4e42316b3697d03864c3d9 | 3 - .../6c7afcf3b8355863bf41a08a735a089c63d97619 | 5 - .../6ce09a7c64f1974210780a4a34799579ec7a7d9d | 0 .../6cfb2d5b94f08a94f93fa79a6fe8d188627c3726 | 0 .../74000b57b46ec5649d24a4a44c0078fef37c5b1d | 3 - .../78379a9bf08c3a5a9f5758bf1d53aa0de51c30e0 | 0 .../79a0cf0b7c12a5a83b517a0fffde2ceb36f9faa6 | 0 .../7de7584f0257906815fef07c873aefd803717632 | 0 .../7f962cf90c92a8c98c2bede425a21459c9478049 | 0 .../819695bbd691d9cb8d93f01e2dc54b18ad28d1be | 0 .../84494ed2c9e27877cd4f0a73b882f0e910e10bfe | 0 .../8cf107426b3e074fb591fc0ed7ecbac63a1d683a | 3 - .../8d4b49f4b412b11789ff892753ecef46f0275255 | 10 -- .../8da02ea2f158d7678e3453f63729dc5f00e56223 | 0 .../90f0a49bee99316d3ae4563676af5456f9180264 | 4 - .../914c9c787aa811309ce5aa7eae3c69aaa021ee64 | 0 .../9cec86a9c116fee7b97f4c98dfefbaf79f64838e | 0 .../9edf5560705f059210d14f2547134079de9f29b2 | 0 .../9fc95465d73516cc9962b4ecd268bbfcfeb8d657 | 13 -- .../a4612392f2a3fd8eb93c098d094e664f0de2614e | 0 .../a5928eaaea1291145941a33dafabc5f76d96ac8a | 0 .../a5cc2925ca8258af241be7e5b0381edf30266302 | 0 .../a9cf2312c9e323db5f0a7e4a1ede8f87bc793fef | 0 .../af4dc7ab45042f5f328a9dd51ed52298e479374d | 0 .../b0a4fbd65c467f4eb0ec18d54e4f58683fefd022 | 0 .../b0b7d3d38cd5e4b212787e75f92bd77b514a5916 | 0 .../c167dcc03d894a7b3d5597899c1da6fdee422084 | 0 .../c74d72b4e43fa64a0908e72d6e6d78a06f7b5742 | 5 - .../caa63e7012d9dda1e866b170ee6033524f8d5f60 | 0 .../e19bd835adbdf3754203158b2ed16a00324f817b | 0 .../e24664ae5eb737f78158eb2cf00be5b3afa23b4c | 3 - .../e4b548f5178cd61ed6190555a66d3c8119420dfa | 0 .../ee9746f00d367e48052bd44f903d1d51e87fe47c | 0 .../f0ad9d0f22f4433924dbb5762cae976aebb496a4 | 0 .../f6e567a035de3bf41d692c148c09cdc1b0908036 | 3 - .../fb6176791068734d5cadb0ede816f19ce9af5d5f | 13 -- .../fcccd944dbd7e0a51dcbeba7c17ba8f121b306d2 | 5 - .../fdf8afbb466b226d23c164e1ab69967a67e4d3f9 | 0 .idea/sonarlint/issuestore/index.pb | 130 ------------------ .../0305bb4613949c92aef5353c1d7a126b6e7579d8 | 0 .../0594be35c2451dc1dad1704a41e3aa7322049c02 | 0 .../0b6cca93c18fd28dfe71f15766b8dae8d1496f5d | 0 .../0f1021f3578e7ad2957e8b008e0bad3162cffa37 | 0 .../11df5582b58bf0be8bd720cf8b57086b5d420e2e | 0 .../17138a271f6b65f6e58ed5c925e5939061efa88b | 0 .../17d87d20633dc9ccd5afcf332b31a9db70d6d03b | 0 .../1b0c45eaf7c34d57e815c9d6ec2511aacd93e4e6 | 0 .../1f9ab227dacaf5f4df91653358b22843c4028842 | 0 .../219600aeaef7272327880879d76afa9a3a3803a9 | 0 .../234a46ce1d1da8058f0c7cff5b5d657bdb9368c2 | 0 .../239ff22be2d75ead1a66ca1e121ff810d9e3ae44 | 0 .../2aade9ec44afbd161df0e408b132ab65c00f0b83 | 0 .../43e24e9dbb55ca782453bd914d361b5d3ada7565 | 0 .../4414d44f588a4ab11d5d0c32c69fdd579d4676cb | 0 .../442292b8a7efeabbe4cc176709b833b1792140ec | 0 .../48f80172f9f06882daf2a436c61d01615425490f | 0 .../4cc49a5ee72f18e86b67c29733dd5f0372aa72ea | 0 .../4dd037fec6dc7041b7ad1034deb31538dec04d54 | 0 .../53ab1377009a1c2afb7687753a40c1a282ed9a01 | 0 .../59dc694635ee875c1a489946d932ba89fb380489 | 0 .../5ac638408c94111e0c72f20a7f7109c7665ab1fa | 0 .../5d83a38896e5b0f4eb5e06e3db5cae5cc8471f07 | 0 .../5e0f556082b2c94ff4f99e1ce3e689554272895a | 0 .../62153552fd0bd9c00e0bdac387e64eb65d3eef7e | 0 .../65994bd67283a1d11002718d81b05f0eb8dd508e | 0 .../6760398c657563eebf4e42316b3697d03864c3d9 | 0 .../6c7afcf3b8355863bf41a08a735a089c63d97619 | 0 .../6ce09a7c64f1974210780a4a34799579ec7a7d9d | 0 .../6cfb2d5b94f08a94f93fa79a6fe8d188627c3726 | 0 .../74000b57b46ec5649d24a4a44c0078fef37c5b1d | 0 .../78379a9bf08c3a5a9f5758bf1d53aa0de51c30e0 | 0 .../79a0cf0b7c12a5a83b517a0fffde2ceb36f9faa6 | 0 .../7de7584f0257906815fef07c873aefd803717632 | 0 .../7f962cf90c92a8c98c2bede425a21459c9478049 | 0 .../819695bbd691d9cb8d93f01e2dc54b18ad28d1be | 0 .../84494ed2c9e27877cd4f0a73b882f0e910e10bfe | 0 .../8cf107426b3e074fb591fc0ed7ecbac63a1d683a | 0 .../8d4b49f4b412b11789ff892753ecef46f0275255 | 0 .../8da02ea2f158d7678e3453f63729dc5f00e56223 | 0 .../90f0a49bee99316d3ae4563676af5456f9180264 | 0 .../914c9c787aa811309ce5aa7eae3c69aaa021ee64 | 0 .../9cec86a9c116fee7b97f4c98dfefbaf79f64838e | 0 .../9edf5560705f059210d14f2547134079de9f29b2 | 0 .../9fc95465d73516cc9962b4ecd268bbfcfeb8d657 | 0 .../a4612392f2a3fd8eb93c098d094e664f0de2614e | 0 .../a5928eaaea1291145941a33dafabc5f76d96ac8a | 0 .../a5cc2925ca8258af241be7e5b0381edf30266302 | 0 .../a9cf2312c9e323db5f0a7e4a1ede8f87bc793fef | 0 .../af4dc7ab45042f5f328a9dd51ed52298e479374d | 0 .../b0a4fbd65c467f4eb0ec18d54e4f58683fefd022 | 0 .../b0b7d3d38cd5e4b212787e75f92bd77b514a5916 | 0 .../c167dcc03d894a7b3d5597899c1da6fdee422084 | 0 .../c74d72b4e43fa64a0908e72d6e6d78a06f7b5742 | 0 .../caa63e7012d9dda1e866b170ee6033524f8d5f60 | 0 .../e19bd835adbdf3754203158b2ed16a00324f817b | 0 .../e24664ae5eb737f78158eb2cf00be5b3afa23b4c | 0 .../e4b548f5178cd61ed6190555a66d3c8119420dfa | 0 .../ee9746f00d367e48052bd44f903d1d51e87fe47c | 0 .../f0ad9d0f22f4433924dbb5762cae976aebb496a4 | 0 .../f6e567a035de3bf41d692c148c09cdc1b0908036 | 0 .../fb6176791068734d5cadb0ede816f19ce9af5d5f | 0 .../fcccd944dbd7e0a51dcbeba7c17ba8f121b306d2 | 0 .../fdf8afbb466b226d23c164e1ab69967a67e4d3f9 | 0 .idea/sonarlint/securityhotspotstore/index.pb | 130 ------------------ .idea/uiDesigner.xml | 124 ----------------- .idea/vcs.xml | 6 - 142 files changed, 566 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/checkstyle-idea.xml delete mode 100644 .idea/code-comments.xml delete mode 100644 .idea/codeStyles/Project.xml delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/discord.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/jpa-buddy.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/sonarlint/issuestore/0/3/0305bb4613949c92aef5353c1d7a126b6e7579d8 delete mode 100644 .idea/sonarlint/issuestore/0/5/0594be35c2451dc1dad1704a41e3aa7322049c02 delete mode 100644 .idea/sonarlint/issuestore/0/b/0b6cca93c18fd28dfe71f15766b8dae8d1496f5d delete mode 100644 .idea/sonarlint/issuestore/0/f/0f1021f3578e7ad2957e8b008e0bad3162cffa37 delete mode 100644 .idea/sonarlint/issuestore/1/1/11df5582b58bf0be8bd720cf8b57086b5d420e2e delete mode 100644 .idea/sonarlint/issuestore/1/7/17138a271f6b65f6e58ed5c925e5939061efa88b delete mode 100644 .idea/sonarlint/issuestore/1/7/17d87d20633dc9ccd5afcf332b31a9db70d6d03b delete mode 100644 .idea/sonarlint/issuestore/1/b/1b0c45eaf7c34d57e815c9d6ec2511aacd93e4e6 delete mode 100644 .idea/sonarlint/issuestore/1/f/1f9ab227dacaf5f4df91653358b22843c4028842 delete mode 100644 .idea/sonarlint/issuestore/2/1/219600aeaef7272327880879d76afa9a3a3803a9 delete mode 100644 .idea/sonarlint/issuestore/2/3/234a46ce1d1da8058f0c7cff5b5d657bdb9368c2 delete mode 100644 .idea/sonarlint/issuestore/2/3/239ff22be2d75ead1a66ca1e121ff810d9e3ae44 delete mode 100644 .idea/sonarlint/issuestore/2/a/2aade9ec44afbd161df0e408b132ab65c00f0b83 delete mode 100644 .idea/sonarlint/issuestore/4/3/43e24e9dbb55ca782453bd914d361b5d3ada7565 delete mode 100644 .idea/sonarlint/issuestore/4/4/4414d44f588a4ab11d5d0c32c69fdd579d4676cb delete mode 100644 .idea/sonarlint/issuestore/4/4/442292b8a7efeabbe4cc176709b833b1792140ec delete mode 100644 .idea/sonarlint/issuestore/4/8/48f80172f9f06882daf2a436c61d01615425490f delete mode 100644 .idea/sonarlint/issuestore/4/c/4cc49a5ee72f18e86b67c29733dd5f0372aa72ea delete mode 100644 .idea/sonarlint/issuestore/4/d/4dd037fec6dc7041b7ad1034deb31538dec04d54 delete mode 100644 .idea/sonarlint/issuestore/5/3/53ab1377009a1c2afb7687753a40c1a282ed9a01 delete mode 100644 .idea/sonarlint/issuestore/5/9/59dc694635ee875c1a489946d932ba89fb380489 delete mode 100644 .idea/sonarlint/issuestore/5/a/5ac638408c94111e0c72f20a7f7109c7665ab1fa delete mode 100644 .idea/sonarlint/issuestore/5/d/5d83a38896e5b0f4eb5e06e3db5cae5cc8471f07 delete mode 100644 .idea/sonarlint/issuestore/5/e/5e0f556082b2c94ff4f99e1ce3e689554272895a delete mode 100644 .idea/sonarlint/issuestore/6/2/62153552fd0bd9c00e0bdac387e64eb65d3eef7e delete mode 100644 .idea/sonarlint/issuestore/6/5/65994bd67283a1d11002718d81b05f0eb8dd508e delete mode 100644 .idea/sonarlint/issuestore/6/7/6760398c657563eebf4e42316b3697d03864c3d9 delete mode 100644 .idea/sonarlint/issuestore/6/c/6c7afcf3b8355863bf41a08a735a089c63d97619 delete mode 100644 .idea/sonarlint/issuestore/6/c/6ce09a7c64f1974210780a4a34799579ec7a7d9d delete mode 100644 .idea/sonarlint/issuestore/6/c/6cfb2d5b94f08a94f93fa79a6fe8d188627c3726 delete mode 100644 .idea/sonarlint/issuestore/7/4/74000b57b46ec5649d24a4a44c0078fef37c5b1d delete mode 100644 .idea/sonarlint/issuestore/7/8/78379a9bf08c3a5a9f5758bf1d53aa0de51c30e0 delete mode 100644 .idea/sonarlint/issuestore/7/9/79a0cf0b7c12a5a83b517a0fffde2ceb36f9faa6 delete mode 100644 .idea/sonarlint/issuestore/7/d/7de7584f0257906815fef07c873aefd803717632 delete mode 100644 .idea/sonarlint/issuestore/7/f/7f962cf90c92a8c98c2bede425a21459c9478049 delete mode 100644 .idea/sonarlint/issuestore/8/1/819695bbd691d9cb8d93f01e2dc54b18ad28d1be delete mode 100644 .idea/sonarlint/issuestore/8/4/84494ed2c9e27877cd4f0a73b882f0e910e10bfe delete mode 100644 .idea/sonarlint/issuestore/8/c/8cf107426b3e074fb591fc0ed7ecbac63a1d683a delete mode 100644 .idea/sonarlint/issuestore/8/d/8d4b49f4b412b11789ff892753ecef46f0275255 delete mode 100644 .idea/sonarlint/issuestore/8/d/8da02ea2f158d7678e3453f63729dc5f00e56223 delete mode 100644 .idea/sonarlint/issuestore/9/0/90f0a49bee99316d3ae4563676af5456f9180264 delete mode 100644 .idea/sonarlint/issuestore/9/1/914c9c787aa811309ce5aa7eae3c69aaa021ee64 delete mode 100644 .idea/sonarlint/issuestore/9/c/9cec86a9c116fee7b97f4c98dfefbaf79f64838e delete mode 100644 .idea/sonarlint/issuestore/9/e/9edf5560705f059210d14f2547134079de9f29b2 delete mode 100644 .idea/sonarlint/issuestore/9/f/9fc95465d73516cc9962b4ecd268bbfcfeb8d657 delete mode 100644 .idea/sonarlint/issuestore/a/4/a4612392f2a3fd8eb93c098d094e664f0de2614e delete mode 100644 .idea/sonarlint/issuestore/a/5/a5928eaaea1291145941a33dafabc5f76d96ac8a delete mode 100644 .idea/sonarlint/issuestore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 delete mode 100644 .idea/sonarlint/issuestore/a/9/a9cf2312c9e323db5f0a7e4a1ede8f87bc793fef delete mode 100644 .idea/sonarlint/issuestore/a/f/af4dc7ab45042f5f328a9dd51ed52298e479374d delete mode 100644 .idea/sonarlint/issuestore/b/0/b0a4fbd65c467f4eb0ec18d54e4f58683fefd022 delete mode 100644 .idea/sonarlint/issuestore/b/0/b0b7d3d38cd5e4b212787e75f92bd77b514a5916 delete mode 100644 .idea/sonarlint/issuestore/c/1/c167dcc03d894a7b3d5597899c1da6fdee422084 delete mode 100644 .idea/sonarlint/issuestore/c/7/c74d72b4e43fa64a0908e72d6e6d78a06f7b5742 delete mode 100644 .idea/sonarlint/issuestore/c/a/caa63e7012d9dda1e866b170ee6033524f8d5f60 delete mode 100644 .idea/sonarlint/issuestore/e/1/e19bd835adbdf3754203158b2ed16a00324f817b delete mode 100644 .idea/sonarlint/issuestore/e/2/e24664ae5eb737f78158eb2cf00be5b3afa23b4c delete mode 100644 .idea/sonarlint/issuestore/e/4/e4b548f5178cd61ed6190555a66d3c8119420dfa delete mode 100644 .idea/sonarlint/issuestore/e/e/ee9746f00d367e48052bd44f903d1d51e87fe47c delete mode 100644 .idea/sonarlint/issuestore/f/0/f0ad9d0f22f4433924dbb5762cae976aebb496a4 delete mode 100644 .idea/sonarlint/issuestore/f/6/f6e567a035de3bf41d692c148c09cdc1b0908036 delete mode 100644 .idea/sonarlint/issuestore/f/b/fb6176791068734d5cadb0ede816f19ce9af5d5f delete mode 100644 .idea/sonarlint/issuestore/f/c/fcccd944dbd7e0a51dcbeba7c17ba8f121b306d2 delete mode 100644 .idea/sonarlint/issuestore/f/d/fdf8afbb466b226d23c164e1ab69967a67e4d3f9 delete mode 100644 .idea/sonarlint/issuestore/index.pb delete mode 100644 .idea/sonarlint/securityhotspotstore/0/3/0305bb4613949c92aef5353c1d7a126b6e7579d8 delete mode 100644 .idea/sonarlint/securityhotspotstore/0/5/0594be35c2451dc1dad1704a41e3aa7322049c02 delete mode 100644 .idea/sonarlint/securityhotspotstore/0/b/0b6cca93c18fd28dfe71f15766b8dae8d1496f5d delete mode 100644 .idea/sonarlint/securityhotspotstore/0/f/0f1021f3578e7ad2957e8b008e0bad3162cffa37 delete mode 100644 .idea/sonarlint/securityhotspotstore/1/1/11df5582b58bf0be8bd720cf8b57086b5d420e2e delete mode 100644 .idea/sonarlint/securityhotspotstore/1/7/17138a271f6b65f6e58ed5c925e5939061efa88b delete mode 100644 .idea/sonarlint/securityhotspotstore/1/7/17d87d20633dc9ccd5afcf332b31a9db70d6d03b delete mode 100644 .idea/sonarlint/securityhotspotstore/1/b/1b0c45eaf7c34d57e815c9d6ec2511aacd93e4e6 delete mode 100644 .idea/sonarlint/securityhotspotstore/1/f/1f9ab227dacaf5f4df91653358b22843c4028842 delete mode 100644 .idea/sonarlint/securityhotspotstore/2/1/219600aeaef7272327880879d76afa9a3a3803a9 delete mode 100644 .idea/sonarlint/securityhotspotstore/2/3/234a46ce1d1da8058f0c7cff5b5d657bdb9368c2 delete mode 100644 .idea/sonarlint/securityhotspotstore/2/3/239ff22be2d75ead1a66ca1e121ff810d9e3ae44 delete mode 100644 .idea/sonarlint/securityhotspotstore/2/a/2aade9ec44afbd161df0e408b132ab65c00f0b83 delete mode 100644 .idea/sonarlint/securityhotspotstore/4/3/43e24e9dbb55ca782453bd914d361b5d3ada7565 delete mode 100644 .idea/sonarlint/securityhotspotstore/4/4/4414d44f588a4ab11d5d0c32c69fdd579d4676cb delete mode 100644 .idea/sonarlint/securityhotspotstore/4/4/442292b8a7efeabbe4cc176709b833b1792140ec delete mode 100644 .idea/sonarlint/securityhotspotstore/4/8/48f80172f9f06882daf2a436c61d01615425490f delete mode 100644 .idea/sonarlint/securityhotspotstore/4/c/4cc49a5ee72f18e86b67c29733dd5f0372aa72ea delete mode 100644 .idea/sonarlint/securityhotspotstore/4/d/4dd037fec6dc7041b7ad1034deb31538dec04d54 delete mode 100644 .idea/sonarlint/securityhotspotstore/5/3/53ab1377009a1c2afb7687753a40c1a282ed9a01 delete mode 100644 .idea/sonarlint/securityhotspotstore/5/9/59dc694635ee875c1a489946d932ba89fb380489 delete mode 100644 .idea/sonarlint/securityhotspotstore/5/a/5ac638408c94111e0c72f20a7f7109c7665ab1fa delete mode 100644 .idea/sonarlint/securityhotspotstore/5/d/5d83a38896e5b0f4eb5e06e3db5cae5cc8471f07 delete mode 100644 .idea/sonarlint/securityhotspotstore/5/e/5e0f556082b2c94ff4f99e1ce3e689554272895a delete mode 100644 .idea/sonarlint/securityhotspotstore/6/2/62153552fd0bd9c00e0bdac387e64eb65d3eef7e delete mode 100644 .idea/sonarlint/securityhotspotstore/6/5/65994bd67283a1d11002718d81b05f0eb8dd508e delete mode 100644 .idea/sonarlint/securityhotspotstore/6/7/6760398c657563eebf4e42316b3697d03864c3d9 delete mode 100644 .idea/sonarlint/securityhotspotstore/6/c/6c7afcf3b8355863bf41a08a735a089c63d97619 delete mode 100644 .idea/sonarlint/securityhotspotstore/6/c/6ce09a7c64f1974210780a4a34799579ec7a7d9d delete mode 100644 .idea/sonarlint/securityhotspotstore/6/c/6cfb2d5b94f08a94f93fa79a6fe8d188627c3726 delete mode 100644 .idea/sonarlint/securityhotspotstore/7/4/74000b57b46ec5649d24a4a44c0078fef37c5b1d delete mode 100644 .idea/sonarlint/securityhotspotstore/7/8/78379a9bf08c3a5a9f5758bf1d53aa0de51c30e0 delete mode 100644 .idea/sonarlint/securityhotspotstore/7/9/79a0cf0b7c12a5a83b517a0fffde2ceb36f9faa6 delete mode 100644 .idea/sonarlint/securityhotspotstore/7/d/7de7584f0257906815fef07c873aefd803717632 delete mode 100644 .idea/sonarlint/securityhotspotstore/7/f/7f962cf90c92a8c98c2bede425a21459c9478049 delete mode 100644 .idea/sonarlint/securityhotspotstore/8/1/819695bbd691d9cb8d93f01e2dc54b18ad28d1be delete mode 100644 .idea/sonarlint/securityhotspotstore/8/4/84494ed2c9e27877cd4f0a73b882f0e910e10bfe delete mode 100644 .idea/sonarlint/securityhotspotstore/8/c/8cf107426b3e074fb591fc0ed7ecbac63a1d683a delete mode 100644 .idea/sonarlint/securityhotspotstore/8/d/8d4b49f4b412b11789ff892753ecef46f0275255 delete mode 100644 .idea/sonarlint/securityhotspotstore/8/d/8da02ea2f158d7678e3453f63729dc5f00e56223 delete mode 100644 .idea/sonarlint/securityhotspotstore/9/0/90f0a49bee99316d3ae4563676af5456f9180264 delete mode 100644 .idea/sonarlint/securityhotspotstore/9/1/914c9c787aa811309ce5aa7eae3c69aaa021ee64 delete mode 100644 .idea/sonarlint/securityhotspotstore/9/c/9cec86a9c116fee7b97f4c98dfefbaf79f64838e delete mode 100644 .idea/sonarlint/securityhotspotstore/9/e/9edf5560705f059210d14f2547134079de9f29b2 delete mode 100644 .idea/sonarlint/securityhotspotstore/9/f/9fc95465d73516cc9962b4ecd268bbfcfeb8d657 delete mode 100644 .idea/sonarlint/securityhotspotstore/a/4/a4612392f2a3fd8eb93c098d094e664f0de2614e delete mode 100644 .idea/sonarlint/securityhotspotstore/a/5/a5928eaaea1291145941a33dafabc5f76d96ac8a delete mode 100644 .idea/sonarlint/securityhotspotstore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 delete mode 100644 .idea/sonarlint/securityhotspotstore/a/9/a9cf2312c9e323db5f0a7e4a1ede8f87bc793fef delete mode 100644 .idea/sonarlint/securityhotspotstore/a/f/af4dc7ab45042f5f328a9dd51ed52298e479374d delete mode 100644 .idea/sonarlint/securityhotspotstore/b/0/b0a4fbd65c467f4eb0ec18d54e4f58683fefd022 delete mode 100644 .idea/sonarlint/securityhotspotstore/b/0/b0b7d3d38cd5e4b212787e75f92bd77b514a5916 delete mode 100644 .idea/sonarlint/securityhotspotstore/c/1/c167dcc03d894a7b3d5597899c1da6fdee422084 delete mode 100644 .idea/sonarlint/securityhotspotstore/c/7/c74d72b4e43fa64a0908e72d6e6d78a06f7b5742 delete mode 100644 .idea/sonarlint/securityhotspotstore/c/a/caa63e7012d9dda1e866b170ee6033524f8d5f60 delete mode 100644 .idea/sonarlint/securityhotspotstore/e/1/e19bd835adbdf3754203158b2ed16a00324f817b delete mode 100644 .idea/sonarlint/securityhotspotstore/e/2/e24664ae5eb737f78158eb2cf00be5b3afa23b4c delete mode 100644 .idea/sonarlint/securityhotspotstore/e/4/e4b548f5178cd61ed6190555a66d3c8119420dfa delete mode 100644 .idea/sonarlint/securityhotspotstore/e/e/ee9746f00d367e48052bd44f903d1d51e87fe47c delete mode 100644 .idea/sonarlint/securityhotspotstore/f/0/f0ad9d0f22f4433924dbb5762cae976aebb496a4 delete mode 100644 .idea/sonarlint/securityhotspotstore/f/6/f6e567a035de3bf41d692c148c09cdc1b0908036 delete mode 100644 .idea/sonarlint/securityhotspotstore/f/b/fb6176791068734d5cadb0ede816f19ce9af5d5f delete mode 100644 .idea/sonarlint/securityhotspotstore/f/c/fcccd944dbd7e0a51dcbeba7c17ba8f121b306d2 delete mode 100644 .idea/sonarlint/securityhotspotstore/f/d/fdf8afbb466b226d23c164e1ab69967a67e4d3f9 delete mode 100644 .idea/sonarlint/securityhotspotstore/index.pb delete mode 100644 .idea/uiDesigner.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml deleted file mode 100644 index f5b372c..0000000 --- a/.idea/checkstyle-idea.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - 10.12.5 - JavaOnly - true - - - \ No newline at end of file diff --git a/.idea/code-comments.xml b/.idea/code-comments.xml deleted file mode 100644 index ec56926..0000000 --- a/.idea/code-comments.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 919ce1f..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index a55e7a1..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml deleted file mode 100644 index 30bab2a..0000000 --- a/.idea/discord.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index aa00ffa..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 927c77c..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/jpa-buddy.xml b/.idea/jpa-buddy.xml deleted file mode 100644 index 966d5f5..0000000 --- a/.idea/jpa-buddy.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index e86209e..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/0/3/0305bb4613949c92aef5353c1d7a126b6e7579d8 b/.idea/sonarlint/issuestore/0/3/0305bb4613949c92aef5353c1d7a126b6e7579d8 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/0/5/0594be35c2451dc1dad1704a41e3aa7322049c02 b/.idea/sonarlint/issuestore/0/5/0594be35c2451dc1dad1704a41e3aa7322049c02 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/0/b/0b6cca93c18fd28dfe71f15766b8dae8d1496f5d b/.idea/sonarlint/issuestore/0/b/0b6cca93c18fd28dfe71f15766b8dae8d1496f5d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/0/f/0f1021f3578e7ad2957e8b008e0bad3162cffa37 b/.idea/sonarlint/issuestore/0/f/0f1021f3578e7ad2957e8b008e0bad3162cffa37 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/1/1/11df5582b58bf0be8bd720cf8b57086b5d420e2e b/.idea/sonarlint/issuestore/1/1/11df5582b58bf0be8bd720cf8b57086b5d420e2e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/1/7/17138a271f6b65f6e58ed5c925e5939061efa88b b/.idea/sonarlint/issuestore/1/7/17138a271f6b65f6e58ed5c925e5939061efa88b deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/1/7/17d87d20633dc9ccd5afcf332b31a9db70d6d03b b/.idea/sonarlint/issuestore/1/7/17d87d20633dc9ccd5afcf332b31a9db70d6d03b deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/1/b/1b0c45eaf7c34d57e815c9d6ec2511aacd93e4e6 b/.idea/sonarlint/issuestore/1/b/1b0c45eaf7c34d57e815c9d6ec2511aacd93e4e6 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/1/f/1f9ab227dacaf5f4df91653358b22843c4028842 b/.idea/sonarlint/issuestore/1/f/1f9ab227dacaf5f4df91653358b22843c4028842 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/2/1/219600aeaef7272327880879d76afa9a3a3803a9 b/.idea/sonarlint/issuestore/2/1/219600aeaef7272327880879d76afa9a3a3803a9 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/2/3/234a46ce1d1da8058f0c7cff5b5d657bdb9368c2 b/.idea/sonarlint/issuestore/2/3/234a46ce1d1da8058f0c7cff5b5d657bdb9368c2 deleted file mode 100644 index df7ad0c..0000000 --- a/.idea/sonarlint/issuestore/2/3/234a46ce1d1da8058f0c7cff5b5d657bdb9368c2 +++ /dev/null @@ -1,5 +0,0 @@ - -K -java:S1948")Make "request" transient or serializable.(8Ź1 -F -java:S1948"*Make "response" transient or serializable.(8Ź1 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/2/3/239ff22be2d75ead1a66ca1e121ff810d9e3ae44 b/.idea/sonarlint/issuestore/2/3/239ff22be2d75ead1a66ca1e121ff810d9e3ae44 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/2/a/2aade9ec44afbd161df0e408b132ab65c00f0b83 b/.idea/sonarlint/issuestore/2/a/2aade9ec44afbd161df0e408b132ab65c00f0b83 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/4/3/43e24e9dbb55ca782453bd914d361b5d3ada7565 b/.idea/sonarlint/issuestore/4/3/43e24e9dbb55ca782453bd914d361b5d3ada7565 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/4/4/4414d44f588a4ab11d5d0c32c69fdd579d4676cb b/.idea/sonarlint/issuestore/4/4/4414d44f588a4ab11d5d0c32c69fdd579d4676cb deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/4/4/442292b8a7efeabbe4cc176709b833b1792140ec b/.idea/sonarlint/issuestore/4/4/442292b8a7efeabbe4cc176709b833b1792140ec deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/4/8/48f80172f9f06882daf2a436c61d01615425490f b/.idea/sonarlint/issuestore/4/8/48f80172f9f06882daf2a436c61d01615425490f deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/4/c/4cc49a5ee72f18e86b67c29733dd5f0372aa72ea b/.idea/sonarlint/issuestore/4/c/4cc49a5ee72f18e86b67c29733dd5f0372aa72ea deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/4/d/4dd037fec6dc7041b7ad1034deb31538dec04d54 b/.idea/sonarlint/issuestore/4/d/4dd037fec6dc7041b7ad1034deb31538dec04d54 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/5/3/53ab1377009a1c2afb7687753a40c1a282ed9a01 b/.idea/sonarlint/issuestore/5/3/53ab1377009a1c2afb7687753a40c1a282ed9a01 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/5/9/59dc694635ee875c1a489946d932ba89fb380489 b/.idea/sonarlint/issuestore/5/9/59dc694635ee875c1a489946d932ba89fb380489 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/5/a/5ac638408c94111e0c72f20a7f7109c7665ab1fa b/.idea/sonarlint/issuestore/5/a/5ac638408c94111e0c72f20a7f7109c7665ab1fa deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/5/d/5d83a38896e5b0f4eb5e06e3db5cae5cc8471f07 b/.idea/sonarlint/issuestore/5/d/5d83a38896e5b0f4eb5e06e3db5cae5cc8471f07 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/5/e/5e0f556082b2c94ff4f99e1ce3e689554272895a b/.idea/sonarlint/issuestore/5/e/5e0f556082b2c94ff4f99e1ce3e689554272895a deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/6/2/62153552fd0bd9c00e0bdac387e64eb65d3eef7e b/.idea/sonarlint/issuestore/6/2/62153552fd0bd9c00e0bdac387e64eb65d3eef7e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/6/5/65994bd67283a1d11002718d81b05f0eb8dd508e b/.idea/sonarlint/issuestore/6/5/65994bd67283a1d11002718d81b05f0eb8dd508e deleted file mode 100644 index 640935d..0000000 --- a/.idea/sonarlint/issuestore/6/5/65994bd67283a1d11002718d81b05f0eb8dd508e +++ /dev/null @@ -1,9 +0,0 @@ - -e -java:S1192"GDefine a constant instead of duplicating this literal " empty" 3 times.(81 -H -java:S3077&"&Use an "AtomicReferenceArray" instead.(81 -X -java:S1117":Rename "result" which hides the field declared at line 43.(81 -H -java:S1181"%Catch Exception instead of Throwable.(81 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/6/7/6760398c657563eebf4e42316b3697d03864c3d9 b/.idea/sonarlint/issuestore/6/7/6760398c657563eebf4e42316b3697d03864c3d9 deleted file mode 100644 index 460b291..0000000 --- a/.idea/sonarlint/issuestore/6/7/6760398c657563eebf4e42316b3697d03864c3d9 +++ /dev/null @@ -1,3 +0,0 @@ - -I -java:S1452"&Remove usage of generic wildcard type.(81 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/6/c/6c7afcf3b8355863bf41a08a735a089c63d97619 b/.idea/sonarlint/issuestore/6/c/6c7afcf3b8355863bf41a08a735a089c63d97619 deleted file mode 100644 index e9e54d8..0000000 --- a/.idea/sonarlint/issuestore/6/c/6c7afcf3b8355863bf41a08a735a089c63d97619 +++ /dev/null @@ -1,5 +0,0 @@ - -F -java:S26290"$Invoke method(s) only conditionally.(81 -G -java:S1948"*Make "delegate" transient or serializable.(˰Տ81 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/6/c/6ce09a7c64f1974210780a4a34799579ec7a7d9d b/.idea/sonarlint/issuestore/6/c/6ce09a7c64f1974210780a4a34799579ec7a7d9d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/6/c/6cfb2d5b94f08a94f93fa79a6fe8d188627c3726 b/.idea/sonarlint/issuestore/6/c/6cfb2d5b94f08a94f93fa79a6fe8d188627c3726 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/7/4/74000b57b46ec5649d24a4a44c0078fef37c5b1d b/.idea/sonarlint/issuestore/7/4/74000b57b46ec5649d24a4a44c0078fef37c5b1d deleted file mode 100644 index 367c131..0000000 --- a/.idea/sonarlint/issuestore/7/4/74000b57b46ec5649d24a4a44c0078fef37c5b1d +++ /dev/null @@ -1,3 +0,0 @@ - -e -java:S2276`"CReplace the call to "Thread.sleep(...)" with a call to "wait(...)".(8ֵ1 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/7/8/78379a9bf08c3a5a9f5758bf1d53aa0de51c30e0 b/.idea/sonarlint/issuestore/7/8/78379a9bf08c3a5a9f5758bf1d53aa0de51c30e0 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/7/9/79a0cf0b7c12a5a83b517a0fffde2ceb36f9faa6 b/.idea/sonarlint/issuestore/7/9/79a0cf0b7c12a5a83b517a0fffde2ceb36f9faa6 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/7/d/7de7584f0257906815fef07c873aefd803717632 b/.idea/sonarlint/issuestore/7/d/7de7584f0257906815fef07c873aefd803717632 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/7/f/7f962cf90c92a8c98c2bede425a21459c9478049 b/.idea/sonarlint/issuestore/7/f/7f962cf90c92a8c98c2bede425a21459c9478049 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/8/1/819695bbd691d9cb8d93f01e2dc54b18ad28d1be b/.idea/sonarlint/issuestore/8/1/819695bbd691d9cb8d93f01e2dc54b18ad28d1be deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/8/4/84494ed2c9e27877cd4f0a73b882f0e910e10bfe b/.idea/sonarlint/issuestore/8/4/84494ed2c9e27877cd4f0a73b882f0e910e10bfe deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/8/c/8cf107426b3e074fb591fc0ed7ecbac63a1d683a b/.idea/sonarlint/issuestore/8/c/8cf107426b3e074fb591fc0ed7ecbac63a1d683a deleted file mode 100644 index 394289a..0000000 --- a/.idea/sonarlint/issuestore/8/c/8cf107426b3e074fb591fc0ed7ecbac63a1d683a +++ /dev/null @@ -1,3 +0,0 @@ - -a -java:S1128"DRemove this unused import 'com.fasterxml.jackson.databind.JsonNode'.(ת81 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/8/d/8d4b49f4b412b11789ff892753ecef46f0275255 b/.idea/sonarlint/issuestore/8/d/8d4b49f4b412b11789ff892753ecef46f0275255 deleted file mode 100644 index a556d1e..0000000 --- a/.idea/sonarlint/issuestore/8/d/8d4b49f4b412b11789ff892753ecef46f0275255 +++ /dev/null @@ -1,10 +0,0 @@ - -s java:S117"QRename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(81 -s java:S117"QRename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(81 -n java:S117"QRename this local variable to match the regular expression '^[a-z][a-zA-Z0-9]*$'.(81 -I -java:S1452"&Remove usage of generic wildcard type.(81 -I -java:S1452"&Remove usage of generic wildcard type.(ꨤ81 -a -java:S4968">Replace this type parametrization by the 'final' type `Class`.(ꨤ81 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/8/d/8da02ea2f158d7678e3453f63729dc5f00e56223 b/.idea/sonarlint/issuestore/8/d/8da02ea2f158d7678e3453f63729dc5f00e56223 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/9/0/90f0a49bee99316d3ae4563676af5456f9180264 b/.idea/sonarlint/issuestore/9/0/90f0a49bee99316d3ae4563676af5456f9180264 deleted file mode 100644 index d3e3b0a..0000000 --- a/.idea/sonarlint/issuestore/9/0/90f0a49bee99316d3ae4563676af5456f9180264 +++ /dev/null @@ -1,4 +0,0 @@ - -L -java:S3740B"/Provide the parametrized type for this generic.(ΰ81 -L java:S1061"+Replace this use of System.out by a logger.(˯81 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/9/1/914c9c787aa811309ce5aa7eae3c69aaa021ee64 b/.idea/sonarlint/issuestore/9/1/914c9c787aa811309ce5aa7eae3c69aaa021ee64 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/9/c/9cec86a9c116fee7b97f4c98dfefbaf79f64838e b/.idea/sonarlint/issuestore/9/c/9cec86a9c116fee7b97f4c98dfefbaf79f64838e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/9/e/9edf5560705f059210d14f2547134079de9f29b2 b/.idea/sonarlint/issuestore/9/e/9edf5560705f059210d14f2547134079de9f29b2 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/9/f/9fc95465d73516cc9962b4ecd268bbfcfeb8d657 b/.idea/sonarlint/issuestore/9/f/9fc95465d73516cc9962b4ecd268bbfcfeb8d657 deleted file mode 100644 index 088d6a3..0000000 --- a/.idea/sonarlint/issuestore/9/f/9fc95465d73516cc9962b4ecd268bbfcfeb8d657 +++ /dev/null @@ -1,13 +0,0 @@ - -W -java:S1141g"5Extract this nested try block into a separate method.(81 -U -java:S1143"7Remove this continue statement from this finally block.(Ɋ81 -o -java:S3776>"RRefactor this method to reduce its Cognitive Complexity from 33 to the 15 allowed.(8ǹ1 -G -java:S1181u"%Catch Exception instead of Throwable.(8ʹ1 -{ -java:S2142i"^Either re-interrupt this method or rethrow the "InterruptedException" that can be caught here.(䠹8˹1 -H -java:S1181"%Catch Exception instead of Throwable.(8͹1 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/a/4/a4612392f2a3fd8eb93c098d094e664f0de2614e b/.idea/sonarlint/issuestore/a/4/a4612392f2a3fd8eb93c098d094e664f0de2614e deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/a/5/a5928eaaea1291145941a33dafabc5f76d96ac8a b/.idea/sonarlint/issuestore/a/5/a5928eaaea1291145941a33dafabc5f76d96ac8a deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 b/.idea/sonarlint/issuestore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/a/9/a9cf2312c9e323db5f0a7e4a1ede8f87bc793fef b/.idea/sonarlint/issuestore/a/9/a9cf2312c9e323db5f0a7e4a1ede8f87bc793fef deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/a/f/af4dc7ab45042f5f328a9dd51ed52298e479374d b/.idea/sonarlint/issuestore/a/f/af4dc7ab45042f5f328a9dd51ed52298e479374d deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/b/0/b0a4fbd65c467f4eb0ec18d54e4f58683fefd022 b/.idea/sonarlint/issuestore/b/0/b0a4fbd65c467f4eb0ec18d54e4f58683fefd022 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/b/0/b0b7d3d38cd5e4b212787e75f92bd77b514a5916 b/.idea/sonarlint/issuestore/b/0/b0b7d3d38cd5e4b212787e75f92bd77b514a5916 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/c/1/c167dcc03d894a7b3d5597899c1da6fdee422084 b/.idea/sonarlint/issuestore/c/1/c167dcc03d894a7b3d5597899c1da6fdee422084 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/c/7/c74d72b4e43fa64a0908e72d6e6d78a06f7b5742 b/.idea/sonarlint/issuestore/c/7/c74d72b4e43fa64a0908e72d6e6d78a06f7b5742 deleted file mode 100644 index 5509231..0000000 --- a/.idea/sonarlint/issuestore/c/7/c74d72b4e43fa64a0908e72d6e6d78a06f7b5742 +++ /dev/null @@ -1,5 +0,0 @@ - -H -java:S1452K"&Remove usage of generic wildcard type.(̽8׎1 -C -java:S1452T"&Remove usage of generic wildcard type.(8ڎ1 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/c/a/caa63e7012d9dda1e866b170ee6033524f8d5f60 b/.idea/sonarlint/issuestore/c/a/caa63e7012d9dda1e866b170ee6033524f8d5f60 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/e/1/e19bd835adbdf3754203158b2ed16a00324f817b b/.idea/sonarlint/issuestore/e/1/e19bd835adbdf3754203158b2ed16a00324f817b deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/e/2/e24664ae5eb737f78158eb2cf00be5b3afa23b4c b/.idea/sonarlint/issuestore/e/2/e24664ae5eb737f78158eb2cf00be5b3afa23b4c deleted file mode 100644 index aae53a3..0000000 --- a/.idea/sonarlint/issuestore/e/2/e24664ae5eb737f78158eb2cf00be5b3afa23b4c +++ /dev/null @@ -1,3 +0,0 @@ - -_ -java:S2094"BRemove this empty class, write its code or make it an "interface".(Ҫ˾8Ј1 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/e/4/e4b548f5178cd61ed6190555a66d3c8119420dfa b/.idea/sonarlint/issuestore/e/4/e4b548f5178cd61ed6190555a66d3c8119420dfa deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/e/e/ee9746f00d367e48052bd44f903d1d51e87fe47c b/.idea/sonarlint/issuestore/e/e/ee9746f00d367e48052bd44f903d1d51e87fe47c deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/f/0/f0ad9d0f22f4433924dbb5762cae976aebb496a4 b/.idea/sonarlint/issuestore/f/0/f0ad9d0f22f4433924dbb5762cae976aebb496a4 deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/sonarlint/issuestore/f/6/f6e567a035de3bf41d692c148c09cdc1b0908036 b/.idea/sonarlint/issuestore/f/6/f6e567a035de3bf41d692c148c09cdc1b0908036 deleted file mode 100644 index 31e73d0..0000000 --- a/.idea/sonarlint/issuestore/f/6/f6e567a035de3bf41d692c148c09cdc1b0908036 +++ /dev/null @@ -1,3 +0,0 @@ - -3 -java:S2187"Add some tests to this class.( \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/f/b/fb6176791068734d5cadb0ede816f19ce9af5d5f b/.idea/sonarlint/issuestore/f/b/fb6176791068734d5cadb0ede816f19ce9af5d5f deleted file mode 100644 index 5da548c..0000000 --- a/.idea/sonarlint/issuestore/f/b/fb6176791068734d5cadb0ede816f19ce9af5d5f +++ /dev/null @@ -1,13 +0,0 @@ - -{ java:S115"ZRename this constant name to match the regular expression '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.(‘81 -{ java:S115"ZRename this constant name to match the regular expression '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.(81 -L java:S106."+Replace this use of System.out by a logger.(ŭ81 -Z -java:S1854J"8Remove this useless assignment to local variable "from".(81 -G java:S106B"+Replace this use of System.out by a logger.(ɳ81 -G java:S106F"+Replace this use of System.out by a logger.(81 -L java:S106H"+Replace this use of System.out by a logger.(Ợ81 -K -java:S1481J")Remove this unused "from" local variable.(81 -L java:S106R"+Replace this use of System.out by a logger.(81 -L java:S106T"+Replace this use of System.out by a logger.(Ľ81 \ No newline at end of file diff --git a/.idea/sonarlint/issuestore/f/c/fcccd944dbd7e0a51dcbeba7c17ba8f121b306d2 b/.idea/sonarlint/issuestore/f/c/fcccd944dbd7e0a51dcbeba7c17ba8f121b306d2 deleted file mode 100644 index cc234bf..0000000 --- a/.idea/sonarlint/issuestore/f/c/fcccd944dbd7e0a51dcbeba7c17ba8f121b306d2 +++ /dev/null @@ -1,5 +0,0 @@ - -R -java:S11170"src/main/java/tech/brenoepic/at4j/util/logging/LoggerUtil.java,9\0\90f0a49bee99316d3ae4563676af5456f9180264 - -Osrc/main/java/tech/brenoepic/at4j/util/logging/FallbackLoggerConfiguration.java,1\7\17d87d20633dc9ccd5afcf332b31a9db70d6d03b -{ -Ksrc/main/java/tech/brenoepic/at4j/util/logging/PrivacyProtectionLogger.java,6\c\6c7afcf3b8355863bf41a08a735a089c63d97619 -v -Fsrc/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimitManager.java,9\f\9fc95465d73516cc9962b4ecd268bbfcfeb8d657 -u -Esrc/main/java/tech/brenoepic/at4j/core/ratelimit/RatelimitBucket.java,c\7\c74d72b4e43fa64a0908e72d6e6d78a06f7b5742 -l -src/main/java/tech/brenoepic/at4j/util/logging/LoggerUtil.java,9\0\90f0a49bee99316d3ae4563676af5456f9180264 - -Osrc/main/java/tech/brenoepic/at4j/util/logging/FallbackLoggerConfiguration.java,1\7\17d87d20633dc9ccd5afcf332b31a9db70d6d03b -{ -Ksrc/main/java/tech/brenoepic/at4j/util/logging/PrivacyProtectionLogger.java,6\c\6c7afcf3b8355863bf41a08a735a089c63d97619 -v -Fsrc/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimitManager.java,9\f\9fc95465d73516cc9962b4ecd268bbfcfeb8d657 -u -Esrc/main/java/tech/brenoepic/at4j/core/ratelimit/RatelimitBucket.java,c\7\c74d72b4e43fa64a0908e72d6e6d78a06f7b5742 -l - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 7f4bedb5b5c8c9f878f482a37be813cb924ac599 Mon Sep 17 00:00:00 2001 From: Breno A Date: Thu, 11 Jan 2024 14:56:52 -0300 Subject: [PATCH 2/4] Create .deepsource.toml --- .deepsource.toml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .deepsource.toml diff --git a/.deepsource.toml b/.deepsource.toml new file mode 100644 index 0000000..d9914df --- /dev/null +++ b/.deepsource.toml @@ -0,0 +1 @@ +version = 1 From 3f1b4af51d7e2076ce846c0c93ef5a85c1c47ef2 Mon Sep 17 00:00:00 2001 From: Breno A Date: Thu, 11 Jan 2024 14:58:16 -0300 Subject: [PATCH 3/4] Update .deepsource.toml --- .deepsource.toml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.deepsource.toml b/.deepsource.toml index d9914df..63b9eb9 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -1 +1,10 @@ version = 1 + +[[analyzers]] +name = "java" + + [analyzers.meta] + runtime_version = "11" + +[[transformers]] +name = "google-java-format" From d128cc68b677487c7c94195d982a0da6fd8aad41 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 17:59:13 +0000 Subject: [PATCH 4/4] style: format code with Google Java Format This commit fixes the style issues introduced in d9c7c4c according to the output from Google Java Format. Details: None --- src/main/java/tech/brenoepic/at4j/AT4J.java | 116 ++- .../java/tech/brenoepic/at4j/AzureApi.java | 123 +-- .../tech/brenoepic/at4j/AzureApiBuilder.java | 164 ++-- .../tech/brenoepic/at4j/azure/BaseURL.java | 78 +- .../brenoepic/at4j/azure/lang/Language.java | 109 ++- .../at4j/azure/lang/LanguageDirection.java | 21 +- .../brenoepic/at4j/core/AzureApiImpl.java | 293 +++---- .../at4j/core/exceptions/AzureException.java | 101 +-- .../AzureExceptionInstantiator.java | 33 +- .../core/exceptions/BadRequestException.java | 32 +- .../core/exceptions/ForbiddenException.java | 30 +- .../InternalServerErrorException.java | 30 +- .../exceptions/MethodNotAllowedException.java | 30 +- .../core/exceptions/NotFoundException.java | 33 +- .../core/exceptions/RatelimitException.java | 27 +- .../exceptions/RequestTimeoutException.java | 30 +- .../ServiceUnavailableException.java | 30 +- .../exceptions/UnauthorizedException.java | 34 +- .../UnsupportedMediaTypeException.java | 30 +- .../at4j/core/ratelimit/LocalRateLimiter.java | 196 ++--- .../at4j/core/ratelimit/RateLimitManager.java | 390 ++++----- .../at4j/core/ratelimit/RateLimiter.java | 22 +- .../at4j/core/ratelimit/RatelimitBucket.java | 303 ++++--- .../at4j/core/thread/AT4JThreadFactory.java | 68 +- .../at4j/core/thread/ThreadPool.java | 123 ++- .../at4j/core/thread/ThreadPoolImpl.java | 162 ++-- .../brenoepic/at4j/data/DetectedLanguage.java | 152 ++-- .../tech/brenoepic/at4j/data/Translation.java | 51 +- .../request/AvailableLanguagesParams.java | 37 +- .../data/request/DetectLanguageParams.java | 29 +- .../at4j/data/request/TranslateParams.java | 377 ++++----- .../data/request/optional/LanguageScope.java | 30 +- .../request/optional/ProfanityAction.java | 29 +- .../request/optional/ProfanityMarker.java | 28 +- .../at4j/data/request/optional/TextType.java | 24 +- .../data/response/TranslationResponse.java | 45 +- .../logging/FallbackLoggerConfiguration.java | 105 ++- .../at4j/util/logging/LoggerUtil.java | 119 +-- .../util/logging/PrivacyProtectionLogger.java | 335 ++++---- .../at4j/util/rest/RestEndpoint.java | 136 ++-- .../brenoepic/at4j/util/rest/RestMethod.java | 16 +- .../brenoepic/at4j/util/rest/RestRequest.java | 768 +++++++++--------- .../rest/RestRequestHttpResponseCode.java | 444 +++++----- .../util/rest/RestRequestInformation.java | 79 +- .../util/rest/RestRequestInformationImpl.java | 99 ++- .../rest/RestRequestResponseInformation.java | 65 +- .../RestRequestResponseInformationImpl.java | 93 +-- .../at4j/util/rest/RestRequestResult.java | 162 ++-- .../util/rest/RestRequestResultErrorCode.java | 446 ++++++---- .../tech/brenoepic/at4j/AzureApiTest.java | 217 +++-- 50 files changed, 3423 insertions(+), 3071 deletions(-) diff --git a/src/main/java/tech/brenoepic/at4j/AT4J.java b/src/main/java/tech/brenoepic/at4j/AT4J.java index 37760a8..d348bb8 100644 --- a/src/main/java/tech/brenoepic/at4j/AT4J.java +++ b/src/main/java/tech/brenoepic/at4j/AT4J.java @@ -6,73 +6,69 @@ import java.util.Properties; public class AT4J { - /** - * The current AT4J version. - * - * @see #DISPLAY_VERSION - */ - public static final String VERSION; + /** + * The current AT4J version. + * + * @see #DISPLAY_VERSION + */ + public static final String VERSION; - /** - * The commit ID from which the current AT4J version was built. - * - * @see #DISPLAY_VERSION - */ - public static final String COMMIT_ID; + /** + * The commit ID from which the current AT4J version was built. + * + * @see #DISPLAY_VERSION + */ + public static final String COMMIT_ID; - /** - * The build timestamp at which the current AT4J version was built. - * - * @see #DISPLAY_VERSION - */ - public static final Instant BUILD_TIMESTAMP; + /** + * The build timestamp at which the current AT4J version was built. + * + * @see #DISPLAY_VERSION + */ + public static final Instant BUILD_TIMESTAMP; + /** + * The display version of the current AT4J version. If the current AT4J version is a release + * version, it is equal to {@link #VERSION}. If the current AT4J version is a snapshot version, it + * consists of the {@link #VERSION}, the {@link #COMMIT_ID}, and the {@link #BUILD_TIMESTAMP}. For + * displaying the version somewhere, it is best to use this constant. + * + * @see #VERSION + * @see #COMMIT_ID + * @see #BUILD_TIMESTAMP + */ + public static final String DISPLAY_VERSION; - /** - * The display version of the current AT4J version. - * If the current AT4J version is a release version, it is equal to {@link #VERSION}. - * If the current AT4J version is a snapshot version, it consists of the {@link #VERSION}, the - * {@link #COMMIT_ID}, and the {@link #BUILD_TIMESTAMP}. - * For displaying the version somewhere, it is best to use this constant. - * - * @see #VERSION - * @see #COMMIT_ID - * @see #BUILD_TIMESTAMP - */ - public static final String DISPLAY_VERSION; - - static { - Properties versionProperties = new Properties(); - try (InputStream versionPropertiesStream = AT4J.class.getResourceAsStream("/git.properties")) { - versionProperties.load(versionPropertiesStream); - } catch (IOException ignored) { - // ignored - } + static { + Properties versionProperties = new Properties(); + try (InputStream versionPropertiesStream = AT4J.class.getResourceAsStream("/git.properties")) { + versionProperties.load(versionPropertiesStream); + } catch (IOException ignored) { + // ignored + } - VERSION = versionProperties.getProperty("version", ""); - COMMIT_ID = versionProperties.getProperty("git.commit.id.abbrev", ""); + VERSION = versionProperties.getProperty("version", ""); + COMMIT_ID = versionProperties.getProperty("git.commit.id.abbrev", ""); - String buildTimestamp = versionProperties.getProperty("buildTimestamp", null); - BUILD_TIMESTAMP = buildTimestamp == null ? null : Instant.parse(buildTimestamp); + String buildTimestamp = versionProperties.getProperty("buildTimestamp", null); + BUILD_TIMESTAMP = buildTimestamp == null ? null : Instant.parse(buildTimestamp); - DISPLAY_VERSION = VERSION.endsWith("-SNAPSHOT") - ? String.format("%s [%s]", VERSION, BUILD_TIMESTAMP) - : VERSION; - } + DISPLAY_VERSION = + VERSION.endsWith("-SNAPSHOT") + ? String.format("%s [%s]", VERSION, BUILD_TIMESTAMP) + : VERSION; + } - /** - * The GitHub url of AT4J. - */ - public static final String GITHUB_URL = "https://github.com/brenoepics/at4j"; + /** The GitHub url of AT4J. */ + public static final String GITHUB_URL = "https://github.com/brenoepics/at4j"; - /** - * The API version from Azure Translator which we are using. - * The reference can be found - * here. - */ - public static final String AZURE_TRANSLATOR_API_VERSION = "3.0"; + /** + * The API version from Azure Translator which we are using. The reference can be found here. + */ + public static final String AZURE_TRANSLATOR_API_VERSION = "3.0"; - private AT4J() { - throw new UnsupportedOperationException(); - } -} \ No newline at end of file + private AT4J() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/AzureApi.java b/src/main/java/tech/brenoepic/at4j/AzureApi.java index 28b2e47..1b5e0aa 100644 --- a/src/main/java/tech/brenoepic/at4j/AzureApi.java +++ b/src/main/java/tech/brenoepic/at4j/AzureApi.java @@ -1,78 +1,85 @@ package tech.brenoepic.at4j; +import java.util.Collection; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; import tech.brenoepic.at4j.azure.BaseURL; import tech.brenoepic.at4j.azure.lang.Language; import tech.brenoepic.at4j.core.thread.ThreadPool; -import tech.brenoepic.at4j.data.request.DetectLanguageParams; -import tech.brenoepic.at4j.data.request.TranslateParams; import tech.brenoepic.at4j.data.DetectedLanguage; import tech.brenoepic.at4j.data.request.AvailableLanguagesParams; +import tech.brenoepic.at4j.data.request.DetectLanguageParams; +import tech.brenoepic.at4j.data.request.TranslateParams; import tech.brenoepic.at4j.data.response.TranslationResponse; -import java.util.Collection; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; - /** - * This class is the most important class of AT4J, as it contains the main methods for translating text. + * This class is the most important class of AT4J, as it contains the main methods for translating + * text. */ public interface AzureApi { - /** - * The BaseURL of the Azure Translator API. - * @see Azure Domain list - */ - BaseURL getBaseURL(); - - /** - * Gets the used subscription key. - * @see Authentication keys and endpoint URL - * - * @return The used subscription key. - */ - String getSubscriptionKey(); + /** + * The BaseURL of the Azure Translator API. + * + * @see Azure + * Domain list + */ + BaseURL getBaseURL(); - /** - * Gets the used subscription region. - *
- * Use with multi-service and regional translator resource. - * The value is the region of the multi-service or regional translator resource. This value is optional when using a global translator resource. - * @see Azure Datacenter List - */ - Optional getSubscriptionRegion(); + /** + * Gets the used subscription key. + * + * @see Authentication + * keys and endpoint URL + * @return The used subscription key. + */ + String getSubscriptionKey(); - ThreadPool getThreadPool(); + /** + * Gets the used subscription region.
+ * Use with multi-service and regional translator resource. The value is the region of the + * multi-service or regional translator resource. This value is optional when using a global + * translator resource. + * + * @see Azure + * Datacenter List + */ + Optional getSubscriptionRegion(); - /** - * Translates the given text from the given source language to the given target language. - * - * @param params The {@link TranslateParams} to translate. - * @return A HashMap result. - */ - CompletableFuture> translate(TranslateParams params); + ThreadPool getThreadPool(); - /** - * Gets the available languages for translation. - * - * @param params The {@link AvailableLanguagesParams} to get the available languages. - * @return The available languages for translation. - * @see Language Support - * - */ - CompletableFuture>> getAvailableLanguages(AvailableLanguagesParams params); + /** + * Translates the given text from the given source language to the given target language. + * + * @param params The {@link TranslateParams} to translate. + * @return A HashMap result. + */ + CompletableFuture> translate(TranslateParams params); + /** + * Gets the available languages for translation. + * + * @param params The {@link AvailableLanguagesParams} to get the available languages. + * @return The available languages for translation. + * @see Language + * Support + */ + CompletableFuture>> getAvailableLanguages( + AvailableLanguagesParams params); - /** - * Detects the language of the given text. - *
- * Limitations: - * The array can have at most 100 elements. - *
- * The entire text included in the request can't exceed 50,000 characters including spaces. - * @param params The {@link DetectLanguageParams} to detect the language. - * @return The detected language. - * @see Language Detection - * - */ - CompletableFuture> detectLanguage(DetectLanguageParams params); + /** + * Detects the language of the given text.
+ * Limitations: The array can have at most 100 elements.
+ * The entire text included in the request can't exceed 50,000 characters including spaces. + * + * @param params The {@link DetectLanguageParams} to detect the language. + * @return The detected language. + * @see Language + * Detection + */ + CompletableFuture> detectLanguage(DetectLanguageParams params); } diff --git a/src/main/java/tech/brenoepic/at4j/AzureApiBuilder.java b/src/main/java/tech/brenoepic/at4j/AzureApiBuilder.java index 7ed8323..da786e4 100644 --- a/src/main/java/tech/brenoepic/at4j/AzureApiBuilder.java +++ b/src/main/java/tech/brenoepic/at4j/AzureApiBuilder.java @@ -4,96 +4,96 @@ import tech.brenoepic.at4j.azure.BaseURL; import tech.brenoepic.at4j.core.AzureApiImpl; - /** * Builder class for constructing instances of AzureApi. + * * @see AzureApi */ public class AzureApiBuilder { - // The HTTP client used by the Azure API. - private OkHttpClient httpClient; - - // The base URL for the Azure API. - private BaseURL baseURL; - - // The subscription key for accessing the Azure API. - private String subscriptionKey; - - // The subscription region for the Azure API. - private String subscriptionRegion; - - /** - * Default constructor initializes the base URL to the global endpoint. - */ - public AzureApiBuilder() { - this.baseURL = BaseURL.GLOBAL; - } - - /** - * Sets the HTTP client used by the Azure API. - * - * @param httpClient The HTTP client used by the Azure API. - * @return The current instance of AzureApiBuilder for method chaining. - * @see OkHttp - */ - public AzureApiBuilder setOkHttpClient(OkHttpClient httpClient) { - this.httpClient = httpClient; - return this; + // The HTTP client used by the Azure API. + private OkHttpClient httpClient; + + // The base URL for the Azure API. + private BaseURL baseURL; + + // The subscription key for accessing the Azure API. + private String subscriptionKey; + + // The subscription region for the Azure API. + private String subscriptionRegion; + + /** Default constructor initializes the base URL to the global endpoint. */ + public AzureApiBuilder() { + this.baseURL = BaseURL.GLOBAL; + } + + /** + * Sets the HTTP client used by the Azure API. + * + * @param httpClient The HTTP client used by the Azure API. + * @return The current instance of AzureApiBuilder for method chaining. + * @see OkHttp + */ + public AzureApiBuilder setOkHttpClient(OkHttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Sets the base URL for the Azure API. + * + * @param baseURL The base URL for the Azure API. + * @return The current instance of AzureApiBuilder for method chaining. + * @see BaseURL + */ + public AzureApiBuilder setBaseURL(BaseURL baseURL) { + this.baseURL = baseURL; + return this; + } + + /** + * Sets the subscription key for accessing the Azure API. + * + * @param subscriptionKey The subscription key for the Azure API. + * @return The current instance of AzureApiBuilder for method chaining. + * @see Authentication + * keys and endpoint URL + */ + public AzureApiBuilder setSubscriptionKey(String subscriptionKey) { + this.subscriptionKey = subscriptionKey; + return this; + } + + /** + * Sets the subscription region for the Azure API. + * + * @param subscriptionRegion The subscription region for the Azure API. + * @return The current instance of AzureApiBuilder for method chaining. + * @see Azure + * Datacenter List + */ + public AzureApiBuilder setSubscriptionRegion(String subscriptionRegion) { + this.subscriptionRegion = subscriptionRegion; + return this; + } + + /** + * Builds and returns an instance of AzureApi with the configured parameters. + * + * @return An instance of AzureApi with the specified configuration. + * @see AzureApi + */ + public AzureApi build() throws IllegalArgumentException { + if (subscriptionKey == null) { + throw new IllegalArgumentException("Subscription key cannot be null"); } - /** - * Sets the base URL for the Azure API. - * - * @param baseURL The base URL for the Azure API. - * @return The current instance of AzureApiBuilder for method chaining. - * @see BaseURL - */ - public AzureApiBuilder setBaseURL(BaseURL baseURL) { - this.baseURL = baseURL; - return this; + if (httpClient == null) { + throw new IllegalArgumentException("HTTP client cannot be null"); } - /** - * Sets the subscription key for accessing the Azure API. - * - * @param subscriptionKey The subscription key for the Azure API. - * @return The current instance of AzureApiBuilder for method chaining. - * @see Authentication keys and endpoint URL - */ - public AzureApiBuilder setSubscriptionKey(String subscriptionKey) { - this.subscriptionKey = subscriptionKey; - return this; - } - - /** - * Sets the subscription region for the Azure API. - * - * @param subscriptionRegion The subscription region for the Azure API. - * @return The current instance of AzureApiBuilder for method chaining. - * @see Azure Datacenter List - */ - public AzureApiBuilder setSubscriptionRegion(String subscriptionRegion) { - this.subscriptionRegion = subscriptionRegion; - return this; - } - - /** - * Builds and returns an instance of AzureApi with the configured parameters. - * - * @return An instance of AzureApi with the specified configuration. - * @see AzureApi - */ - public AzureApi build() throws IllegalArgumentException { - if (subscriptionKey == null) { - throw new IllegalArgumentException("Subscription key cannot be null"); - } - - if (httpClient == null) { - throw new IllegalArgumentException("HTTP client cannot be null"); - } - - return new AzureApiImpl(httpClient, baseURL, subscriptionKey, subscriptionRegion); - } + return new AzureApiImpl(httpClient, baseURL, subscriptionKey, subscriptionRegion); + } } - diff --git a/src/main/java/tech/brenoepic/at4j/azure/BaseURL.java b/src/main/java/tech/brenoepic/at4j/azure/BaseURL.java index f167716..665b34f 100644 --- a/src/main/java/tech/brenoepic/at4j/azure/BaseURL.java +++ b/src/main/java/tech/brenoepic/at4j/azure/BaseURL.java @@ -1,48 +1,44 @@ package tech.brenoepic.at4j.azure; /** - * The base URL of the Azure Translator API. - * The list of available domains can be found - * here. + * The base URL of the Azure Translator API. The list of available domains can be found here. */ public enum BaseURL { - /** - * The default domain of the Azure Translator API. - * Datacenters: Closest available datacenter. - */ - GLOBAL("api.cognitive.microsofttranslator.com"), - - /** - * The domain of the Azure Translator API for the Asia Pacific. - * Datacenters: Korea South, Japan East, Southeast Asia, and Australia East. - */ - ASIA_PACIFIC("api-apc.cognitive.microsofttranslator.com"), - - /** - * The domain of the Azure Translator API for the Europe. - * Datacenters: North Europe and West Europe. - */ - EUROPE("api-eur.cognitive.microsofttranslator.com"), - - /** - * The domain of the Azure Translator API for the United States. - * Datacenters: East US, South Central US, West Central US, and West US 2 - */ - UNITED_STATES("api-nam.cognitive.microsofttranslator.com"); - - private final String url; - - BaseURL(String url) { - this.url = url; - } - - /** - * Gets the URL of the Azure Translator API. - * - * @return The URL of the Azure Translator API. - */ - public String getUrl() { - return url; - } + /** The default domain of the Azure Translator API. Datacenters: Closest available datacenter. */ + GLOBAL("api.cognitive.microsofttranslator.com"), + + /** + * The domain of the Azure Translator API for the Asia Pacific. Datacenters: Korea South, Japan + * East, Southeast Asia, and Australia East. + */ + ASIA_PACIFIC("api-apc.cognitive.microsofttranslator.com"), + + /** + * The domain of the Azure Translator API for the Europe. Datacenters: North Europe and West + * Europe. + */ + EUROPE("api-eur.cognitive.microsofttranslator.com"), + + /** + * The domain of the Azure Translator API for the United States. Datacenters: East US, South + * Central US, West Central US, and West US 2 + */ + UNITED_STATES("api-nam.cognitive.microsofttranslator.com"); + + private final String url; + + BaseURL(String url) { + this.url = url; + } + + /** + * Gets the URL of the Azure Translator API. + * + * @return The URL of the Azure Translator API. + */ + public String getUrl() { + return url; + } } diff --git a/src/main/java/tech/brenoepic/at4j/azure/lang/Language.java b/src/main/java/tech/brenoepic/at4j/azure/lang/Language.java index 41e89ac..67dc455 100644 --- a/src/main/java/tech/brenoepic/at4j/azure/lang/Language.java +++ b/src/main/java/tech/brenoepic/at4j/azure/lang/Language.java @@ -4,45 +4,72 @@ public class Language { - private String code; - private String name; - private String nativeName; - private LanguageDirection direction; - - public Language(String code, String name, String nativeName, LanguageDirection direction) { - this.code = code; - this.name = name; - this.nativeName = nativeName; - this.direction = direction; - } - - public static Language ofJSON(String code, ObjectNode json) { - return new Language( - code, - json.get("name").asText(), - json.get("nativeName").asText(), - LanguageDirection.fromString(json.get("dir").asText()) - ); - } - - @Override - public String toString() { - return "Language{" + - "code='" + code + '\'' + - ", name='" + name + '\'' + - ", nativeName='" + nativeName + '\'' + - ", direction=" + direction + - '}'; - } - - public String getCode() { return code; } - public void setCode(String value) { this.code = value; } - public String getName() { return name; } - public void setName(String value) { this.name = value; } - - public String getNativeName() { return nativeName; } - public void setNativeName(String value) { this.nativeName = value; } - - public LanguageDirection getDir() { return direction; } - public void setDir(LanguageDirection value) { this.direction = value; } + private String code; + private String name; + private String nativeName; + private LanguageDirection direction; + + public Language(String code, String name, String nativeName, LanguageDirection direction) { + this.code = code; + this.name = name; + this.nativeName = nativeName; + this.direction = direction; + } + + public static Language ofJSON(String code, ObjectNode json) { + return new Language( + code, + json.get("name").asText(), + json.get("nativeName").asText(), + LanguageDirection.fromString(json.get("dir").asText())); + } + + @Override + public String toString() { + return "Language{" + + "code='" + + code + + '\'' + + ", name='" + + name + + '\'' + + ", nativeName='" + + nativeName + + '\'' + + ", direction=" + + direction + + '}'; + } + + public String getCode() { + return code; + } + + public void setCode(String value) { + this.code = value; + } + + public String getName() { + return name; + } + + public void setName(String value) { + this.name = value; + } + + public String getNativeName() { + return nativeName; + } + + public void setNativeName(String value) { + this.nativeName = value; + } + + public LanguageDirection getDir() { + return direction; + } + + public void setDir(LanguageDirection value) { + this.direction = value; + } } diff --git a/src/main/java/tech/brenoepic/at4j/azure/lang/LanguageDirection.java b/src/main/java/tech/brenoepic/at4j/azure/lang/LanguageDirection.java index b02b277..d0aa99b 100644 --- a/src/main/java/tech/brenoepic/at4j/azure/lang/LanguageDirection.java +++ b/src/main/java/tech/brenoepic/at4j/azure/lang/LanguageDirection.java @@ -1,17 +1,18 @@ package tech.brenoepic.at4j.azure.lang; public enum LanguageDirection { - LTR, RTL; + LTR, + RTL; - public static LanguageDirection fromString(String value) { - if (value.equalsIgnoreCase("ltr")) { - return LTR; - } - - if (value.equalsIgnoreCase("rtl")) { - return RTL; - } + public static LanguageDirection fromString(String value) { + if (value.equalsIgnoreCase("ltr")) { + return LTR; + } - throw new IllegalArgumentException("Invalid value for LanguageDirection: " + value); + if (value.equalsIgnoreCase("rtl")) { + return RTL; } + + throw new IllegalArgumentException("Invalid value for LanguageDirection: " + value); + } } diff --git a/src/main/java/tech/brenoepic/at4j/core/AzureApiImpl.java b/src/main/java/tech/brenoepic/at4j/core/AzureApiImpl.java index 94cb653..174ca6e 100644 --- a/src/main/java/tech/brenoepic/at4j/core/AzureApiImpl.java +++ b/src/main/java/tech/brenoepic/at4j/core/AzureApiImpl.java @@ -3,6 +3,10 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; import okhttp3.OkHttpClient; import tech.brenoepic.at4j.AzureApi; import tech.brenoepic.at4j.azure.BaseURL; @@ -20,166 +24,165 @@ import tech.brenoepic.at4j.util.rest.RestMethod; import tech.brenoepic.at4j.util.rest.RestRequest; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; - public class AzureApiImpl implements AzureApi { - /** - * The Http Client for this instance. - */ - private final OkHttpClient httpClient; - - /** - * The BaseURL for this instance. - */ - private final BaseURL baseURL; - - /** - * The subscription key for this instance. - */ - private final String subscriptionKey; - - /** - * The subscription region for this instance. - */ - private final String subscriptionRegion; - - /** - * The object mapper for this instance. - */ - private final ObjectMapper objectMapper = new ObjectMapper(); - - /** - * The ratelimit manager for this resource. - */ - private final RateLimitManager ratelimitManager = new RateLimitManager(this); - - /** - * The thread pool which is used internally. - */ - private final ThreadPoolImpl threadPool = new ThreadPoolImpl(); - - /** - * Constructor for AzureApiImpl. - * - * @param httpClient The Http Client for this instance. - * @param baseURL The BaseURL for this instance. - * @param subscriptionKey The subscription key for this instance. - * @param subscriptionRegion The subscription region for this instance. - */ - public AzureApiImpl(OkHttpClient httpClient, BaseURL baseURL, String subscriptionKey, String subscriptionRegion) { - this.httpClient = httpClient; - this.baseURL = baseURL; - this.subscriptionKey = subscriptionKey; - this.subscriptionRegion = subscriptionRegion; - } - - - @Override - public BaseURL getBaseURL() { - return this.baseURL; - } - - @Override - public String getSubscriptionKey() { - return this.subscriptionKey; - } - - @Override - public Optional getSubscriptionRegion() { - return Optional.ofNullable(this.subscriptionRegion); - } - - @Override - public ThreadPool getThreadPool() { - return threadPool; + /** The Http Client for this instance. */ + private final OkHttpClient httpClient; + + /** The BaseURL for this instance. */ + private final BaseURL baseURL; + + /** The subscription key for this instance. */ + private final String subscriptionKey; + + /** The subscription region for this instance. */ + private final String subscriptionRegion; + + /** The object mapper for this instance. */ + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** The ratelimit manager for this resource. */ + private final RateLimitManager ratelimitManager = new RateLimitManager(this); + + /** The thread pool which is used internally. */ + private final ThreadPoolImpl threadPool = new ThreadPoolImpl(); + + /** + * Constructor for AzureApiImpl. + * + * @param httpClient The Http Client for this instance. + * @param baseURL The BaseURL for this instance. + * @param subscriptionKey The subscription key for this instance. + * @param subscriptionRegion The subscription region for this instance. + */ + public AzureApiImpl( + OkHttpClient httpClient, BaseURL baseURL, String subscriptionKey, String subscriptionRegion) { + this.httpClient = httpClient; + this.baseURL = baseURL; + this.subscriptionKey = subscriptionKey; + this.subscriptionRegion = subscriptionRegion; + } + + @Override + public BaseURL getBaseURL() { + return this.baseURL; + } + + @Override + public String getSubscriptionKey() { + return this.subscriptionKey; + } + + @Override + public Optional getSubscriptionRegion() { + return Optional.ofNullable(this.subscriptionRegion); + } + + @Override + public ThreadPool getThreadPool() { + return threadPool; + } + + @Override + public CompletableFuture> translate(TranslateParams params) { + if (params.getText() == null || params.getText().isEmpty()) { + return CompletableFuture.completedFuture(Optional.empty()); } - - @Override - public CompletableFuture> translate(TranslateParams params) { - if (params.getText() == null || params.getText().isEmpty()) { - return CompletableFuture.completedFuture(Optional.empty()); - } - - RestRequest> request = new RestRequest>(this, RestMethod.POST, RestEndpoint.TRANSLATE).setBody(params.getBody()); - params.getQueryParameters().forEach(request::addQueryParameter); - params.getTargetLanguages().forEach(lang -> request.addQueryParameter("to", lang)); - - return request.execute(response -> { - if (response.getJsonBody().isNull() || !response.getJsonBody().has(0) || !response.getJsonBody().get(0).has("translations")) - return Optional.empty(); - - JsonNode jsonNode = response.getJsonBody().get(0); - Collection translations = new ArrayList<>(); - jsonNode.get("translations").forEach(node -> translations.add(Translation.ofJSON((ObjectNode) node))); - - TranslationResponse translationResponse = new TranslationResponse(translations); - if (jsonNode.has("detectedLanguage")) { - JsonNode detectedLanguage = jsonNode.get("detectedLanguage"); - translationResponse.setDetectedLanguage(DetectedLanguage.ofJSON((ObjectNode) detectedLanguage)); - } - - return Optional.of(translationResponse); + RestRequest> request = + new RestRequest>( + this, RestMethod.POST, RestEndpoint.TRANSLATE) + .setBody(params.getBody()); + params.getQueryParameters().forEach(request::addQueryParameter); + params.getTargetLanguages().forEach(lang -> request.addQueryParameter("to", lang)); + + return request.execute( + response -> { + if (response.getJsonBody().isNull() + || !response.getJsonBody().has(0) + || !response.getJsonBody().get(0).has("translations")) return Optional.empty(); + + JsonNode jsonNode = response.getJsonBody().get(0); + Collection translations = new ArrayList<>(); + jsonNode + .get("translations") + .forEach(node -> translations.add(Translation.ofJSON((ObjectNode) node))); + + TranslationResponse translationResponse = new TranslationResponse(translations); + if (jsonNode.has("detectedLanguage")) { + JsonNode detectedLanguage = jsonNode.get("detectedLanguage"); + translationResponse.setDetectedLanguage( + DetectedLanguage.ofJSON((ObjectNode) detectedLanguage)); + } + + return Optional.of(translationResponse); }); - } - - @Override - public CompletableFuture> detectLanguage(DetectLanguageParams params) { - if(params.getText() == null || params.getText().isEmpty()) { - return CompletableFuture.completedFuture(Optional.empty()); - } - - RestRequest> request = new RestRequest>(this, RestMethod.POST, RestEndpoint.DETECT).setBody(params.getBody()); + } - return request.execute(response -> { - if (response.getJsonBody().isNull() || !response.getJsonBody().has(0) || !response.getJsonBody().get(0).has("language")) - return Optional.empty(); - - JsonNode jsonNode = response.getJsonBody().get(0); - if (!jsonNode.isObject()) return Optional.empty(); - - return Optional.of(DetectedLanguage.ofJSON((ObjectNode) jsonNode)); - }); + @Override + public CompletableFuture> detectLanguage(DetectLanguageParams params) { + if (params.getText() == null || params.getText().isEmpty()) { + return CompletableFuture.completedFuture(Optional.empty()); } + RestRequest> request = + new RestRequest>(this, RestMethod.POST, RestEndpoint.DETECT) + .setBody(params.getBody()); - @Override - public CompletableFuture>> getAvailableLanguages(AvailableLanguagesParams params) { - RestRequest>> request = new RestRequest>>(this, RestMethod.GET, RestEndpoint.LANGUAGES) - .addQueryParameter("scope", params.getScope()).includeAuthorizationHeader(false); - - if (params.getSourceLanguage() != null) { - request.addHeader("Accept-Language", params.getSourceLanguage()); - } - - return request.execute(response -> { - if (response.getJsonBody().isNull() || !response.getJsonBody().has("translation")) return Optional.empty(); + return request.execute( + response -> { + if (response.getJsonBody().isNull() + || !response.getJsonBody().has(0) + || !response.getJsonBody().get(0).has("language")) return Optional.empty(); - Collection languages = new ArrayList<>(); - JsonNode jsonNode = response.getJsonBody().get("translation"); - jsonNode.fieldNames().forEachRemaining(key -> { - Language language = Language.ofJSON(key, (ObjectNode) jsonNode.get(key)); - languages.add(language); - }); + JsonNode jsonNode = response.getJsonBody().get(0); + if (!jsonNode.isObject()) return Optional.empty(); - return Optional.of(languages); + return Optional.of(DetectedLanguage.ofJSON((ObjectNode) jsonNode)); }); + } + + @Override + public CompletableFuture>> getAvailableLanguages( + AvailableLanguagesParams params) { + RestRequest>> request = + new RestRequest>>( + this, RestMethod.GET, RestEndpoint.LANGUAGES) + .addQueryParameter("scope", params.getScope()) + .includeAuthorizationHeader(false); + + if (params.getSourceLanguage() != null) { + request.addHeader("Accept-Language", params.getSourceLanguage()); } - public OkHttpClient getHttpClient() { - return this.httpClient; - } + return request.execute( + response -> { + if (response.getJsonBody().isNull() || !response.getJsonBody().has("translation")) + return Optional.empty(); + + Collection languages = new ArrayList<>(); + JsonNode jsonNode = response.getJsonBody().get("translation"); + jsonNode + .fieldNames() + .forEachRemaining( + key -> { + Language language = Language.ofJSON(key, (ObjectNode) jsonNode.get(key)); + languages.add(language); + }); + + return Optional.of(languages); + }); + } - public ObjectMapper getObjectMapper() { - return objectMapper; - } + public OkHttpClient getHttpClient() { + return this.httpClient; + } - public RateLimitManager getRatelimitManager() { - return ratelimitManager; - } + public ObjectMapper getObjectMapper() { + return objectMapper; + } + public RateLimitManager getRatelimitManager() { + return ratelimitManager; + } } diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/AzureException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/AzureException.java index 4c19491..1dd7416 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/AzureException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/AzureException.java @@ -1,56 +1,57 @@ package tech.brenoepic.at4j.core.exceptions; -import tech.brenoepic.at4j.util.rest.*; import java.util.Optional; +import tech.brenoepic.at4j.util.rest.*; -/** - * This exception is always thrown whenever a request to azure failed. - */ +/** This exception is always thrown whenever a request to azure failed. */ public class AzureException extends Exception { - /** - * The request. May be null if the exception was thrown before creating a request. - */ - private final RestRequestInformation request; - - /** - * The rest request result. May be null if the exception was thrown before sending a request. - */ - private final RestRequestResponseInformation response; - - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public AzureException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(message, origin); - this.request = request; - this.response = response; - } - - /** - * Gets information about the request which caused the exception. - * May be null if the exception was thrown before creating a request. - * - * @return Information about the request which caused the exception. - */ - public Optional getRequest() { - return Optional.ofNullable(request); - } - - /** - * Gets information about the response which caused the exception. - * May not be present if the exception was thrown before sending a request. - * - * @return Information about the response which caused the exception. - */ - public Optional getResponse() { - return Optional.ofNullable(response); - } - -} \ No newline at end of file + /** + * The request. May be null if the exception was thrown before creating a request. + */ + private final RestRequestInformation request; + + /** + * The rest request result. May be null if the exception was thrown before sending a + * request. + */ + private final RestRequestResponseInformation response; + + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public AzureException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(message, origin); + this.request = request; + this.response = response; + } + + /** + * Gets information about the request which caused the exception. May be null if the + * exception was thrown before creating a request. + * + * @return Information about the request which caused the exception. + */ + public Optional getRequest() { + return Optional.ofNullable(request); + } + + /** + * Gets information about the response which caused the exception. May not be present if the + * exception was thrown before sending a request. + * + * @return Information about the response which caused the exception. + */ + public Optional getResponse() { + return Optional.ofNullable(response); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/AzureExceptionInstantiator.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/AzureExceptionInstantiator.java index 7c85a00..1b2f439 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/AzureExceptionInstantiator.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/AzureExceptionInstantiator.java @@ -1,28 +1,29 @@ package tech.brenoepic.at4j.core.exceptions; - import tech.brenoepic.at4j.util.rest.RestRequestInformation; import tech.brenoepic.at4j.util.rest.RestRequestResponseInformation; /** - * Represents a function that accepts four arguments ({@code Exception}, {@code String}, {@code RestRequest} and - * {@code RestRequestResult}) and produces a azure exception of type {@code T}. + * Represents a function that accepts four arguments ({@code Exception}, {@code String}, {@code + * RestRequest} and {@code RestRequestResult}) and produces a azure exception of type {@code T}. * * @param The type of the azure exception that is produced. */ @FunctionalInterface public interface AzureExceptionInstantiator { - /** - * Creates a new instance of the class {@code T}. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - * @return The new instance. - */ - T createInstance(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response); - -} \ No newline at end of file + /** + * Creates a new instance of the class {@code T}. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + * @return The new instance. + */ + T createInstance( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response); +} diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/BadRequestException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/BadRequestException.java index 101a048..3d78ff5 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/BadRequestException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/BadRequestException.java @@ -3,22 +3,22 @@ import tech.brenoepic.at4j.util.rest.RestRequestInformation; import tech.brenoepic.at4j.util.rest.RestRequestResponseInformation; -/** - * When we sent a bad request (HTTP response code 400). - */ +/** When we sent a bad request (HTTP response code 400). */ public class BadRequestException extends AzureException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public BadRequestException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(origin, message, request, response); - } - + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public BadRequestException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(origin, message, request, response); + } } diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/ForbiddenException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/ForbiddenException.java index 31fb80e..6e9cba1 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/ForbiddenException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/ForbiddenException.java @@ -5,17 +5,19 @@ public class ForbiddenException extends AzureException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public ForbiddenException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(origin, message, request, response); - } - -} \ No newline at end of file + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public ForbiddenException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(origin, message, request, response); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/InternalServerErrorException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/InternalServerErrorException.java index 473408e..d6f591e 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/InternalServerErrorException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/InternalServerErrorException.java @@ -5,17 +5,19 @@ public class InternalServerErrorException extends AzureException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public InternalServerErrorException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(origin, message, request, response); - } - -} \ No newline at end of file + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public InternalServerErrorException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(origin, message, request, response); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/MethodNotAllowedException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/MethodNotAllowedException.java index 88634f9..5737de7 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/MethodNotAllowedException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/MethodNotAllowedException.java @@ -5,17 +5,19 @@ public class MethodNotAllowedException extends AzureException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public MethodNotAllowedException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(origin, message, request, response); - } - -} \ No newline at end of file + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public MethodNotAllowedException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(origin, message, request, response); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/NotFoundException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/NotFoundException.java index 221e07d..99dd4ce 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/NotFoundException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/NotFoundException.java @@ -1,25 +1,24 @@ package tech.brenoepic.at4j.core.exceptions; - import tech.brenoepic.at4j.util.rest.RestRequestInformation; import tech.brenoepic.at4j.util.rest.RestRequestResponseInformation; -/** - * When something was not found (HTTP response code 404). - */ +/** When something was not found (HTTP response code 404). */ public class NotFoundException extends BadRequestException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public NotFoundException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(origin, message, request, response); - } - + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public NotFoundException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(origin, message, request, response); + } } diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/RatelimitException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/RatelimitException.java index 523f82f..80a0209 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/RatelimitException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/RatelimitException.java @@ -2,20 +2,17 @@ import tech.brenoepic.at4j.util.rest.RestRequestInformation; -/** - * When we encounter a rate limit and run out of retiring. - */ +/** When we encounter a rate limit and run out of retiring. */ public class RatelimitException extends AzureException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - */ - public RatelimitException(Exception origin, String message, RestRequestInformation request) { - super(origin, message, request, null); - } - -} \ No newline at end of file + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + */ + public RatelimitException(Exception origin, String message, RestRequestInformation request) { + super(origin, message, request, null); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/RequestTimeoutException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/RequestTimeoutException.java index ebdd554..ef62118 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/RequestTimeoutException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/RequestTimeoutException.java @@ -5,17 +5,19 @@ public class RequestTimeoutException extends AzureException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public RequestTimeoutException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(origin, message, request, response); - } - -} \ No newline at end of file + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public RequestTimeoutException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(origin, message, request, response); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/ServiceUnavailableException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/ServiceUnavailableException.java index 57c7357..001128b 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/ServiceUnavailableException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/ServiceUnavailableException.java @@ -5,17 +5,19 @@ public class ServiceUnavailableException extends AzureException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public ServiceUnavailableException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(origin, message, request, response); - } - -} \ No newline at end of file + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public ServiceUnavailableException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(origin, message, request, response); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/UnauthorizedException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/UnauthorizedException.java index 641d6b7..2200c44 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/UnauthorizedException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/UnauthorizedException.java @@ -3,22 +3,22 @@ import tech.brenoepic.at4j.util.rest.RestRequestInformation; import tech.brenoepic.at4j.util.rest.RestRequestResponseInformation; -/** - * When we sent a bad request (HTTP response code 400). - */ +/** When we sent a bad request (HTTP response code 400). */ public class UnauthorizedException extends AzureException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public UnauthorizedException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(origin, message, request, response); - } - -} \ No newline at end of file + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public UnauthorizedException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(origin, message, request, response); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/exceptions/UnsupportedMediaTypeException.java b/src/main/java/tech/brenoepic/at4j/core/exceptions/UnsupportedMediaTypeException.java index 13d4bdd..f62069e 100644 --- a/src/main/java/tech/brenoepic/at4j/core/exceptions/UnsupportedMediaTypeException.java +++ b/src/main/java/tech/brenoepic/at4j/core/exceptions/UnsupportedMediaTypeException.java @@ -5,17 +5,19 @@ public class UnsupportedMediaTypeException extends AzureException { - /** - * Creates a new instance of this class. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - */ - public UnsupportedMediaTypeException(Exception origin, String message, RestRequestInformation request, - RestRequestResponseInformation response) { - super(origin, message, request, response); - } - -} \ No newline at end of file + /** + * Creates a new instance of this class. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + */ + public UnsupportedMediaTypeException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + super(origin, message, request, response); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/ratelimit/LocalRateLimiter.java b/src/main/java/tech/brenoepic/at4j/core/ratelimit/LocalRateLimiter.java index 93dcbc3..6509ad4 100644 --- a/src/main/java/tech/brenoepic/at4j/core/ratelimit/LocalRateLimiter.java +++ b/src/main/java/tech/brenoepic/at4j/core/ratelimit/LocalRateLimiter.java @@ -5,115 +5,123 @@ /** * An implementation of {@code Ratelimiter} that allows for simple local ratelimits. * - *

To compensate for misalignment with the real global ratelimit bucket, it is recommended to not set the value - * to the exact global ratelimit but a lower value. If the global ratelimit for your bot is 50 requests / 1 second - * (the default), you should choose a value that prevents overlapping with the real bucket. This can be achieved with - * the following rules: + *

To compensate for misalignment with the real global ratelimit bucket, it is recommended to not + * set the value to the exact global ratelimit but a lower value. If the global ratelimit for your + * bot is 50 requests / 1 second (the default), you should choose a value that prevents overlapping + * with the real bucket. This can be achieved with the following rules: + * *

    - *
  • Choose an {@code amount} that is between {@code 1} and half of the real amount - * (in this example {@code 1} - {@code 25}). - *
  • Calculate the {@code bucketDuration} using {@code (amount * realDuration) / (realAmount - amount)}. + *
  • Choose an {@code amount} that is between {@code 1} and half of the real amount (in this + * example {@code 1} - {@code 25}). + *
  • Calculate the {@code bucketDuration} using {@code (amount * realDuration) / (realAmount - + * amount)}. *
- * For the 50 requests / 1 second ratelimit, these rules allow the following ratelimits (only a subset): + * + * For the 50 requests / 1 second ratelimit, these rules allow the following ratelimits (only a + * subset): + * *
    - *
  • About {@code 1} request per {@code 21 ms} - * ({@code amount = 1} and {@code bucketDuration = Duration.ofMillis((long) Math.ceil(1000D / 49D))}) - *
  • About {@code 5} request per {@code 112 ms} - * ({@code amount = 5} and {@code bucketDuration = Duration.ofMillis((long) Math.ceil(5000D / 45D))}). - *
  • {@code 10} request per {@code 250 ms} - * ({@code amount = 10} and {@code bucketDuration = Duration.ofMillis((long) Math.ceil(10000D / 40D))}). - *
  • {@code 25} request per {@code 1 sec} - * ({@code amount = 25} and {@code bucketDuration = Duration.ofMillis((long) Math.ceil(25000D / 25D))}). + *
  • About {@code 1} request per {@code 21 ms} ({@code amount = 1} and {@code bucketDuration = + * Duration.ofMillis((long) Math.ceil(1000D / 49D))}) + *
  • About {@code 5} request per {@code 112 ms} ({@code amount = 5} and {@code bucketDuration = + * Duration.ofMillis((long) Math.ceil(5000D / 45D))}). + *
  • {@code 10} request per {@code 250 ms} ({@code amount = 10} and {@code bucketDuration = + * Duration.ofMillis((long) Math.ceil(10000D / 40D))}). + *
  • {@code 25} request per {@code 1 sec} ({@code amount = 25} and {@code bucketDuration = + * Duration.ofMillis((long) Math.ceil(25000D / 25D))}). *
- * Choosing a lower {@code amount} increases the maximum throughput but can limit your ability to perform actions - * in bulk. * - * @see Azure RateLimit Docs + * Choosing a lower {@code amount} increases the maximum throughput but can limit your ability to + * perform actions in bulk. + * + * @see Azure + * RateLimit Docs */ public class LocalRateLimiter implements RateLimiter { - private volatile long nextResetNanos; - private volatile int remainingQuota; + private volatile long nextResetNanos; + private volatile int remainingQuota; - private final int amount; - private final Duration bucketDuration; + private final int amount; + private final Duration bucketDuration; - /** - * Creates a new local ratelimiter. - * - * @param amount The amount available per reset interval. - * @param bucketDuration The time to wait until the available quota resets. - */ - public LocalRateLimiter(int amount, Duration bucketDuration) { - this.amount = amount; - this.bucketDuration = bucketDuration; - } + /** + * Creates a new local ratelimiter. + * + * @param amount The amount available per reset interval. + * @param bucketDuration The time to wait until the available quota resets. + */ + public LocalRateLimiter(int amount, Duration bucketDuration) { + this.amount = amount; + this.bucketDuration = bucketDuration; + } - /** - * Gets the amount available per reset interval. - * - * @return The amount. - */ - public int getAmount() { - return amount; - } + /** + * Gets the amount available per reset interval. + * + * @return The amount. + */ + public int getAmount() { + return amount; + } - /** - * Gets the time to wait until the available quota resets. - * - * @return The time to wait until the available quota resets. - */ - public Duration getBucketDuration() { - return bucketDuration; - } + /** + * Gets the time to wait until the available quota resets. + * + * @return The time to wait until the available quota resets. + */ + public Duration getBucketDuration() { + return bucketDuration; + } - /** - * Gets the next time the quota resets. - * - *

Use {@link System#nanoTime()} to calculate the absolute difference. - * - * @return The next time the quota resets. Can be in the past. - */ - public long getNextResetNanos() { - return nextResetNanos; - } - - /** - * Gets the remaining quota in the current reset interval. - * - * @return The remaining quota. - */ - public int getRemainingQuota() { - return remainingQuota; - } + /** + * Gets the next time the quota resets. + * + *

Use {@link System#nanoTime()} to calculate the absolute difference. + * + * @return The next time the quota resets. Can be in the past. + */ + public long getNextResetNanos() { + return nextResetNanos; + } - @Override - public synchronized void requestQuota() throws InterruptedException { - if (remainingQuota <= 0) { - // Wait until a new quota becomes available - long sleepTime; - while ((sleepTime = calculateSleepTime()) > 0) { // Sleep is unreliable, so we have to loop - Thread.sleep(sleepTime / 1_000_000, (int) (sleepTime % 1_000_000)); - } - } + /** + * Gets the remaining quota in the current reset interval. + * + * @return The remaining quota. + */ + public int getRemainingQuota() { + return remainingQuota; + } - // Reset the limit when the last reset timestamp is past - if (System.nanoTime() >= nextResetNanos) { - remainingQuota = amount; - try { - nextResetNanos = System.nanoTime() + bucketDuration.toNanos(); - } catch (ArithmeticException e) { - // An ArithmeticException means that the duration was too large to be represented - // as a long. While such a value is completely non-sense and should not be used, we - // still don't want an exception. - nextResetNanos = Long.MAX_VALUE; - } - } - - remainingQuota--; + @Override + public synchronized void requestQuota() throws InterruptedException { + if (remainingQuota <= 0) { + // Wait until a new quota becomes available + long sleepTime; + while ((sleepTime = calculateSleepTime()) > 0) { // Sleep is unreliable, so we have to loop + Thread.sleep(sleepTime / 1_000_000, (int) (sleepTime % 1_000_000)); + } } - private long calculateSleepTime() { - return nextResetNanos - System.nanoTime(); + // Reset the limit when the last reset timestamp is past + if (System.nanoTime() >= nextResetNanos) { + remainingQuota = amount; + try { + nextResetNanos = System.nanoTime() + bucketDuration.toNanos(); + } catch (ArithmeticException e) { + // An ArithmeticException means that the duration was too large to be represented + // as a long. While such a value is completely non-sense and should not be used, we + // still don't want an exception. + nextResetNanos = Long.MAX_VALUE; + } } -} \ No newline at end of file + + remainingQuota--; + } + + private long calculateSleepTime() { + return nextResetNanos - System.nanoTime(); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimitManager.java b/src/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimitManager.java index 1166228..728abbe 100644 --- a/src/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimitManager.java +++ b/src/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimitManager.java @@ -1,5 +1,10 @@ package tech.brenoepic.at4j.core.ratelimit; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; import okhttp3.Response; import org.apache.logging.log4j.Logger; import tech.brenoepic.at4j.core.AzureApiImpl; @@ -9,206 +14,217 @@ import tech.brenoepic.at4j.util.rest.RestRequestResponseInformationImpl; import tech.brenoepic.at4j.util.rest.RestRequestResult; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; - -/** - * This class manages rate-limits and keeps track of them. - */ +/** This class manages rate-limits and keeps track of them. */ public class RateLimitManager { - /** - * The (logger) of this class. - */ - private static final Logger logger = LoggerUtil.getLogger(RateLimitManager.class); - - /** - * The Azure API instance for this rate-limit manager. - */ - private final AzureApiImpl api; - - /** - * All buckets. - */ - private final Set buckets = new HashSet<>(); - - /** - * Creates a new rate-limit manager. - * - * @param api The azure api instance for this rate-limit manager. - */ - public RateLimitManager(AzureApiImpl api) { - this.api = api; + /** The (logger) of this class. */ + private static final Logger logger = LoggerUtil.getLogger(RateLimitManager.class); + + /** The Azure API instance for this rate-limit manager. */ + private final AzureApiImpl api; + + /** All buckets. */ + private final Set buckets = new HashSet<>(); + + /** + * Creates a new rate-limit manager. + * + * @param api The azure api instance for this rate-limit manager. + */ + public RateLimitManager(AzureApiImpl api) { + this.api = api; + } + + /** + * Gets all rate-limit buckets. + * + * @return All rate-limit buckets. + */ + public Set getBuckets() { + return buckets; + } + + /** + * Queues the given request. This method is automatically called when using {@link + * RestRequest#execute(Function)}! + * + * @param request The request to queue. + */ + public void queueRequest(RestRequest request) { + final RatelimitBucket bucket; + final boolean alreadyInQueue; + synchronized (buckets) { + // Search for a bucket that fits to this request + bucket = + buckets.stream() + .filter( + b -> b.equals(request.getEndpoint(), request.getMajorUrlParameter().orElse(null))) + .findAny() + .orElseGet( + () -> + new RatelimitBucket( + api, request.getEndpoint(), request.getMajorUrlParameter().orElse(null))); + + // Must be executed BEFORE adding the request to the queue + alreadyInQueue = bucket.peekRequestFromQueue() != null; + + // Add the bucket to the set of buckets (does nothing if it's already in the set) + buckets.add(bucket); + + // Add the request to the bucket's queue + bucket.addRequestToQueue(request); } - /** - * Gets all rate-limit buckets. - * - * @return All rate-limit buckets. - */ - public Set getBuckets() { - return buckets; + // If the bucket is already in the queue, there's nothing more to do + if (alreadyInQueue) { + return; } - /** - * Queues the given request. - * This method is automatically called when using {@link RestRequest#execute(Function)}! - * - * @param request The request to queue. - */ - public void queueRequest(RestRequest request) { - final RatelimitBucket bucket; - final boolean alreadyInQueue; - synchronized (buckets) { - // Search for a bucket that fits to this request - bucket = buckets.stream() - .filter(b -> b.equals(request.getEndpoint(), request.getMajorUrlParameter().orElse(null))) - .findAny() - .orElseGet(() -> new RatelimitBucket( - api, request.getEndpoint(), request.getMajorUrlParameter().orElse(null))); - - // Must be executed BEFORE adding the request to the queue - alreadyInQueue = bucket.peekRequestFromQueue() != null; - - // Add the bucket to the set of buckets (does nothing if it's already in the set) - buckets.add(bucket); - - // Add the request to the bucket's queue - bucket.addRequestToQueue(request); - } - - // If the bucket is already in the queue, there's nothing more to do - if (alreadyInQueue) { - return; - } - - // Start working of the queue - api.getThreadPool().getExecutorService().submit(() -> { - RestRequest currentRequest = bucket.peekRequestFromQueue(); - RestRequestResult result = null; - long responseTimestamp = System.currentTimeMillis(); - while (currentRequest != null) { + // Start working of the queue + api.getThreadPool() + .getExecutorService() + .submit( + () -> { + RestRequest currentRequest = bucket.peekRequestFromQueue(); + RestRequestResult result = null; + long responseTimestamp = System.currentTimeMillis(); + while (currentRequest != null) { try { - int sleepTime = bucket.getTimeTillSpaceGetsAvailable(); - if (sleepTime > 0) { - logger.debug("Delaying requests to {} for {}ms to prevent hitting ratelimits", - bucket, sleepTime); - } - - // Sleep until space is available - while (sleepTime > 0) { - try { - Thread.sleep(sleepTime); - } catch (InterruptedException e) { - logger.warn("We got interrupted while waiting for a rate limit!", e); - } - // Update in case something changed (e.g. because we hit a global rate-limit) - sleepTime = bucket.getTimeTillSpaceGetsAvailable(); + int sleepTime = bucket.getTimeTillSpaceGetsAvailable(); + if (sleepTime > 0) { + logger.debug( + "Delaying requests to {} for {}ms to prevent hitting ratelimits", + bucket, + sleepTime); + } + + // Sleep until space is available + while (sleepTime > 0) { + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + logger.warn("We got interrupted while waiting for a rate limit!", e); } + // Update in case something changed (e.g. because we hit a global rate-limit) + sleepTime = bucket.getTimeTillSpaceGetsAvailable(); + } - // Execute the request - result = currentRequest.executeBlocking(); + // Execute the request + result = currentRequest.executeBlocking(); - // Calculate the time offset if it wasn't done before - responseTimestamp = System.currentTimeMillis(); + // Calculate the time offset if it wasn't done before + responseTimestamp = System.currentTimeMillis(); } catch (Throwable t) { - responseTimestamp = System.currentTimeMillis(); - if (currentRequest.getResult().isDone()) { - logger.warn("Received exception for a request that is already done. " - + "This should not be able to happen!", t); - } - // Try to get the response from the exception if it exists - if (t instanceof AzureException) { - result = ((AzureException) t).getResponse() - .map(RestRequestResponseInformationImpl.class::cast) - .map(RestRequestResponseInformationImpl::getRestRequestResult) - .orElse(null); - } - // Complete the request - currentRequest.getResult().completeExceptionally(t); + responseTimestamp = System.currentTimeMillis(); + if (currentRequest.getResult().isDone()) { + logger.warn( + "Received exception for a request that is already done. " + + "This should not be able to happen!", + t); + } + // Try to get the response from the exception if it exists + if (t instanceof AzureException) { + result = + ((AzureException) t) + .getResponse() + .map(RestRequestResponseInformationImpl.class::cast) + .map(RestRequestResponseInformationImpl::getRestRequestResult) + .orElse(null); + } + // Complete the request + currentRequest.getResult().completeExceptionally(t); } finally { - try { - // Handle the response - handleResponse(currentRequest, result, bucket, responseTimestamp); - } catch (Throwable t) { - logger.warn("Encountered unexpected exception.", t); - } - - // The request didn't finish, so let's try again - if (!currentRequest.getResult().isDone()) { - continue; - } - - // Poll a new quest - synchronized (buckets) { - bucket.pollRequestFromQueue(); - currentRequest = bucket.peekRequestFromQueue(); - if (currentRequest == null) { - buckets.remove(bucket); - } + try { + // Handle the response + handleResponse(currentRequest, result, bucket, responseTimestamp); + } catch (Throwable t) { + logger.warn("Encountered unexpected exception.", t); + } + + // The request didn't finish, so let's try again + if (!currentRequest.getResult().isDone()) { + continue; + } + + // Poll a new quest + synchronized (buckets) { + bucket.pollRequestFromQueue(); + currentRequest = bucket.peekRequestFromQueue(); + if (currentRequest == null) { + buckets.remove(bucket); } + } } - } - }); + } + }); + } + + /** + * Updates the rate-limit information and sets the result if the request was successful. + * + * @param request The request. + * @param result The result of the request. + * @param bucket The bucket the request belongs to. + * @param responseTimestamp The timestamp directly after the response finished. + */ + private void handleResponse( + RestRequest request, + RestRequestResult result, + RatelimitBucket bucket, + long responseTimestamp) { + if (result == null || result.getResponse() == null) { + return; } - - /** - * Updates the rate-limit information and sets the result if the request was successful. - * - * @param request The request. - * @param result The result of the request. - * @param bucket The bucket the request belongs to. - * @param responseTimestamp The timestamp directly after the response finished. - */ - private void handleResponse( - RestRequest request, RestRequestResult result, RatelimitBucket bucket, long responseTimestamp) { - if (result == null || result.getResponse() == null) { - return; - } - Response response = result.getResponse(); - boolean global = Objects.requireNonNull(response.header("X-RateLimit-Global", "false")).equalsIgnoreCase("true"); - int remaining = Integer.parseInt(Objects.requireNonNull(response.header("X-RateLimit-Remaining", "1"))); - long reset = (long) (Double.parseDouble(Objects.requireNonNull(response.header("X-RateLimit-Reset", "0"))) * 1000); - - // Check if we received a 429 response - if (result.getResponse().code() == 429) { - if (response.header("Via") == null) { - logger.warn("Hit a CloudFlare API ban! This means you were sending a very large " - + "amount of invalid requests."); - long retryAfter = Long.parseLong(Objects.requireNonNull(response.header("Retry-after"))) * 1000; - RatelimitBucket.setGlobalRatelimitResetTimestamp(api, responseTimestamp + retryAfter); - return; - } - long retryAfter = - result.getJsonBody().isNull() - ? 0 : (long) (result.getJsonBody().get("retry_after").asDouble() * 1000); - - if (global) { - // We hit a global rate-limit. Time to panic! - logger.warn("Hit a global rate-limit! This means you were sending a very large " - + "amount within a very short time frame."); - RatelimitBucket.setGlobalRatelimitResetTimestamp(api, responseTimestamp + retryAfter); - } else { - logger.debug("Received a 429 response from Discord! Recalculating time offset..."); - - // Update the bucket information - bucket.setRatelimitRemaining(0); - bucket.setRatelimitResetTimestamp(responseTimestamp + retryAfter); - } - } else { - // Check if we didn't already complete it exceptionally. - CompletableFuture requestResult = request.getResult(); - if (!requestResult.isDone()) { - requestResult.complete(result); - } - - // Update bucket information - bucket.setRatelimitRemaining(remaining); - bucket.setRatelimitResetTimestamp(reset); - } + Response response = result.getResponse(); + boolean global = + Objects.requireNonNull(response.header("X-RateLimit-Global", "false")) + .equalsIgnoreCase("true"); + int remaining = + Integer.parseInt(Objects.requireNonNull(response.header("X-RateLimit-Remaining", "1"))); + long reset = + (long) + (Double.parseDouble(Objects.requireNonNull(response.header("X-RateLimit-Reset", "0"))) + * 1000); + + // Check if we received a 429 response + if (result.getResponse().code() == 429) { + if (response.header("Via") == null) { + logger.warn( + "Hit a CloudFlare API ban! This means you were sending a very large " + + "amount of invalid requests."); + long retryAfter = + Long.parseLong(Objects.requireNonNull(response.header("Retry-after"))) * 1000; + RatelimitBucket.setGlobalRatelimitResetTimestamp(api, responseTimestamp + retryAfter); + return; + } + long retryAfter = + result.getJsonBody().isNull() + ? 0 + : (long) (result.getJsonBody().get("retry_after").asDouble() * 1000); + + if (global) { + // We hit a global rate-limit. Time to panic! + logger.warn( + "Hit a global rate-limit! This means you were sending a very large " + + "amount within a very short time frame."); + RatelimitBucket.setGlobalRatelimitResetTimestamp(api, responseTimestamp + retryAfter); + } else { + logger.debug("Received a 429 response from Discord! Recalculating time offset..."); + + // Update the bucket information + bucket.setRatelimitRemaining(0); + bucket.setRatelimitResetTimestamp(responseTimestamp + retryAfter); + } + } else { + // Check if we didn't already complete it exceptionally. + CompletableFuture requestResult = request.getResult(); + if (!requestResult.isDone()) { + requestResult.complete(result); + } + + // Update bucket information + bucket.setRatelimitRemaining(remaining); + bucket.setRatelimitResetTimestamp(reset); } - -} \ No newline at end of file + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimiter.java b/src/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimiter.java index d290c8d..5981af6 100644 --- a/src/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimiter.java +++ b/src/main/java/tech/brenoepic/at4j/core/ratelimit/RateLimiter.java @@ -1,17 +1,13 @@ package tech.brenoepic.at4j.core.ratelimit; -/** - * Can be used to implement ratelimits. - */ +/** Can be used to implement ratelimits. */ public interface RateLimiter { - /** - * Blocks the requesting thread until a quota becomes available. - * - * @throws InterruptedException if any thread has interrupted the current thread. - * The interrupted status of the current thread is cleared when this exception is - * thrown. - */ - void requestQuota() throws InterruptedException; - -} \ No newline at end of file + /** + * Blocks the requesting thread until a quota becomes available. + * + * @throws InterruptedException if any thread has interrupted the current thread. The interrupted + * status of the current thread is cleared when this exception is thrown. + */ + void requestQuota() throws InterruptedException; +} diff --git a/src/main/java/tech/brenoepic/at4j/core/ratelimit/RatelimitBucket.java b/src/main/java/tech/brenoepic/at4j/core/ratelimit/RatelimitBucket.java index 00ada41..667dd52 100644 --- a/src/main/java/tech/brenoepic/at4j/core/ratelimit/RatelimitBucket.java +++ b/src/main/java/tech/brenoepic/at4j/core/ratelimit/RatelimitBucket.java @@ -1,164 +1,161 @@ package tech.brenoepic.at4j.core.ratelimit; - +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import tech.brenoepic.at4j.AzureApi; import tech.brenoepic.at4j.core.AzureApiImpl; import tech.brenoepic.at4j.util.rest.RestEndpoint; import tech.brenoepic.at4j.util.rest.RestRequest; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - public class RatelimitBucket { - // The key is the subscription key, as global ratelimits are shared across the same account. - private static final Map globalRatelimitResetTimestamp = new ConcurrentHashMap<>(); - - private final AzureApiImpl api; - - private final ConcurrentLinkedQueue> requestQueue = new ConcurrentLinkedQueue<>(); - - private final RestEndpoint endpoint; - private final String majorUrlParameter; - - private volatile long ratelimitResetTimestamp = 0; - private volatile int ratelimitRemaining = 1; - - /** - * Creates a RatelimitBucket for the given endpoint / parameter combination. - * - * @param api The api/shard to use. - * @param endpoint The REST endpoint the ratelimit is tracked for. - */ - public RatelimitBucket(AzureApi api, RestEndpoint endpoint) { - this(api, endpoint, null); - } - - /** - * Creates a RatelimitBucket for the given endpoint / parameter combination. - * - * @param api The api/shard to use. - * @param endpoint The REST endpoint the ratelimit is tracked for. - * @param majorUrlParameter The url parameter this bucket is specific for. May be null. - */ - public RatelimitBucket(AzureApi api, RestEndpoint endpoint, String majorUrlParameter) { - this.api = (AzureApiImpl) api; - this.endpoint = endpoint; - this.majorUrlParameter = majorUrlParameter; - } - - /** - * Sets a global ratelimit. - * - * @param api A azure api instance. - * @param resetTimestamp The reset timestamp of the global ratelimit. - */ - public static void setGlobalRatelimitResetTimestamp(AzureApi api, long resetTimestamp) { - globalRatelimitResetTimestamp.put(api.getSubscriptionKey(), resetTimestamp); - } - - /** - * Adds the given request to the bucket's queue. - * - * @param request The request to add. - */ - public void addRequestToQueue(RestRequest request) { - requestQueue.add(request); + // The key is the subscription key, as global ratelimits are shared across the same account. + private static final Map globalRatelimitResetTimestamp = new ConcurrentHashMap<>(); + + private final AzureApiImpl api; + + private final ConcurrentLinkedQueue> requestQueue = new ConcurrentLinkedQueue<>(); + + private final RestEndpoint endpoint; + private final String majorUrlParameter; + + private volatile long ratelimitResetTimestamp = 0; + private volatile int ratelimitRemaining = 1; + + /** + * Creates a RatelimitBucket for the given endpoint / parameter combination. + * + * @param api The api/shard to use. + * @param endpoint The REST endpoint the ratelimit is tracked for. + */ + public RatelimitBucket(AzureApi api, RestEndpoint endpoint) { + this(api, endpoint, null); + } + + /** + * Creates a RatelimitBucket for the given endpoint / parameter combination. + * + * @param api The api/shard to use. + * @param endpoint The REST endpoint the ratelimit is tracked for. + * @param majorUrlParameter The url parameter this bucket is specific for. May be null. + */ + public RatelimitBucket(AzureApi api, RestEndpoint endpoint, String majorUrlParameter) { + this.api = (AzureApiImpl) api; + this.endpoint = endpoint; + this.majorUrlParameter = majorUrlParameter; + } + + /** + * Sets a global ratelimit. + * + * @param api A azure api instance. + * @param resetTimestamp The reset timestamp of the global ratelimit. + */ + public static void setGlobalRatelimitResetTimestamp(AzureApi api, long resetTimestamp) { + globalRatelimitResetTimestamp.put(api.getSubscriptionKey(), resetTimestamp); + } + + /** + * Adds the given request to the bucket's queue. + * + * @param request The request to add. + */ + public void addRequestToQueue(RestRequest request) { + requestQueue.add(request); + } + + /** + * Polls a request from the bucket's queue. + * + * @return The polled request. + */ + public RestRequest pollRequestFromQueue() { + return requestQueue.poll(); + } + + /** + * Peeks a request from the bucket's queue. + * + * @return The peeked request. + */ + public RestRequest peekRequestFromQueue() { + return requestQueue.peek(); + } + + /** + * Sets the remaining requests till ratelimit. + * + * @param ratelimitRemaining The remaining requests till ratelimit. + */ + public void setRatelimitRemaining(int ratelimitRemaining) { + this.ratelimitRemaining = ratelimitRemaining; + } + + /** + * Sets the ratelimit reset timestamp. + * + * @param ratelimitResetTimestamp The ratelimit reset timestamp. + */ + public void setRatelimitResetTimestamp(long ratelimitResetTimestamp) { + this.ratelimitResetTimestamp = ratelimitResetTimestamp; + } + + /** + * Gets the time in seconds how long you have to wait till there's space in the bucket again. + * + * @return The time in seconds how long you have to wait till there's space in the bucket again. + */ + public int getTimeTillSpaceGetsAvailable() { + long globalRLResetTimestamp = + RatelimitBucket.globalRatelimitResetTimestamp.getOrDefault(api.getSubscriptionKey(), 0L); + long timestamp = System.currentTimeMillis(); + if (ratelimitRemaining > 0 && (globalRLResetTimestamp - timestamp) <= 0) { + return 0; } - - /** - * Polls a request from the bucket's queue. - * - * @return The polled request. - */ - public RestRequest pollRequestFromQueue() { - return requestQueue.poll(); - } - - /** - * Peeks a request from the bucket's queue. - * - * @return The peeked request. - */ - public RestRequest peekRequestFromQueue() { - return requestQueue.peek(); - } - - /** - * Sets the remaining requests till ratelimit. - * - * @param ratelimitRemaining The remaining requests till ratelimit. - */ - public void setRatelimitRemaining(int ratelimitRemaining) { - this.ratelimitRemaining = ratelimitRemaining; - } - - /** - * Sets the ratelimit reset timestamp. - * - * @param ratelimitResetTimestamp The ratelimit reset timestamp. - */ - public void setRatelimitResetTimestamp(long ratelimitResetTimestamp) { - this.ratelimitResetTimestamp = ratelimitResetTimestamp; - } - - /** - * Gets the time in seconds how long you have to wait till there's space in the bucket again. - * - * @return The time in seconds how long you have to wait till there's space in the bucket again. - */ - public int getTimeTillSpaceGetsAvailable() { - long globalRLResetTimestamp = - RatelimitBucket.globalRatelimitResetTimestamp.getOrDefault(api.getSubscriptionKey(), 0L); - long timestamp = System.currentTimeMillis(); - if (ratelimitRemaining > 0 && (globalRLResetTimestamp - timestamp) <= 0) { - return 0; - } - return (int) (Math.max(ratelimitResetTimestamp, globalRLResetTimestamp) - timestamp); - } - - /** - * Checks if a bucket created with the given parameters would equal this bucket. - * - * @param endpoint The endpoint. - * @param majorUrlParameter The major url parameter. - * @return Whether a bucket created with the given parameters would equal this bucket or not. - */ - public boolean equals(RestEndpoint endpoint, String majorUrlParameter) { - boolean endpointSame = this.endpoint == endpoint; - boolean majorUrlParameterBothNull = this.majorUrlParameter == null && majorUrlParameter == null; - boolean majorUrlParameterEqual = - this.majorUrlParameter != null && this.majorUrlParameter.equals(majorUrlParameter); - - return endpointSame && (majorUrlParameterBothNull || majorUrlParameterEqual); - } - - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof RatelimitBucket)) { - return false; - } - RatelimitBucket otherBucket = (RatelimitBucket) obj; - return equals(otherBucket.endpoint, otherBucket.majorUrlParameter); - } - - @Override - public int hashCode() { - int hash = 42; - int urlParamHash = majorUrlParameter == null ? 0 : majorUrlParameter.hashCode(); - int endpointHash = endpoint == null ? 0 : endpoint.hashCode(); - - hash = hash * 11 + urlParamHash; - hash = hash * 17 + endpointHash; - return hash; - } - - @Override - public String toString() { - String str = "Endpoint: " + (endpoint == null ? "global" : endpoint.getEndpointUrl()); - str += ", Major url parameter:" + (majorUrlParameter == null ? "none" : majorUrlParameter); - return str; + return (int) (Math.max(ratelimitResetTimestamp, globalRLResetTimestamp) - timestamp); + } + + /** + * Checks if a bucket created with the given parameters would equal this bucket. + * + * @param endpoint The endpoint. + * @param majorUrlParameter The major url parameter. + * @return Whether a bucket created with the given parameters would equal this bucket or not. + */ + public boolean equals(RestEndpoint endpoint, String majorUrlParameter) { + boolean endpointSame = this.endpoint == endpoint; + boolean majorUrlParameterBothNull = this.majorUrlParameter == null && majorUrlParameter == null; + boolean majorUrlParameterEqual = + this.majorUrlParameter != null && this.majorUrlParameter.equals(majorUrlParameter); + + return endpointSame && (majorUrlParameterBothNull || majorUrlParameterEqual); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof RatelimitBucket)) { + return false; } -} \ No newline at end of file + RatelimitBucket otherBucket = (RatelimitBucket) obj; + return equals(otherBucket.endpoint, otherBucket.majorUrlParameter); + } + + @Override + public int hashCode() { + int hash = 42; + int urlParamHash = majorUrlParameter == null ? 0 : majorUrlParameter.hashCode(); + int endpointHash = endpoint == null ? 0 : endpoint.hashCode(); + + hash = hash * 11 + urlParamHash; + hash = hash * 17 + endpointHash; + return hash; + } + + @Override + public String toString() { + String str = "Endpoint: " + (endpoint == null ? "global" : endpoint.getEndpointUrl()); + str += ", Major url parameter:" + (majorUrlParameter == null ? "none" : majorUrlParameter); + return str; + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/thread/AT4JThreadFactory.java b/src/main/java/tech/brenoepic/at4j/core/thread/AT4JThreadFactory.java index a95f9c8..eb0cb14 100644 --- a/src/main/java/tech/brenoepic/at4j/core/thread/AT4JThreadFactory.java +++ b/src/main/java/tech/brenoepic/at4j/core/thread/AT4JThreadFactory.java @@ -1,44 +1,36 @@ package tech.brenoepic.at4j.core.thread; -import org.jetbrains.annotations.NotNull; - import java.util.concurrent.atomic.AtomicInteger; +import org.jetbrains.annotations.NotNull; -/** - * A thread factory that creates optionally numbered threads as daemon or non-daemon. - */ +/** A thread factory that creates optionally numbered threads as daemon or non-daemon. */ public class AT4JThreadFactory implements java.util.concurrent.ThreadFactory { - /** - * The numbering counter. - */ - private final AtomicInteger counter = new AtomicInteger(); - - /** - * The name pattern. - */ - private final String namePattern; - - /** - * Whether to create daemon threads. - */ - private final boolean daemon; - - /** - * Creates a new thread factory. - * - * @param namePattern The name pattern may contain a {@code %d} wildcard where the counter gets filled in. - * @param daemon Whether to create daemon or non-daemon threads. - */ - public AT4JThreadFactory(String namePattern, boolean daemon) { - this.namePattern = namePattern; - this.daemon = daemon; - } - - @Override - public Thread newThread(@NotNull Runnable r) { - Thread thread = new Thread(r, String.format(namePattern, counter.incrementAndGet())); - thread.setDaemon(daemon); - return thread; - } -} \ No newline at end of file + /** The numbering counter. */ + private final AtomicInteger counter = new AtomicInteger(); + + /** The name pattern. */ + private final String namePattern; + + /** Whether to create daemon threads. */ + private final boolean daemon; + + /** + * Creates a new thread factory. + * + * @param namePattern The name pattern may contain a {@code %d} wildcard where the counter gets + * filled in. + * @param daemon Whether to create daemon or non-daemon threads. + */ + public AT4JThreadFactory(String namePattern, boolean daemon) { + this.namePattern = namePattern; + this.daemon = daemon; + } + + @Override + public Thread newThread(@NotNull Runnable r) { + Thread thread = new Thread(r, String.format(namePattern, counter.incrementAndGet())); + thread.setDaemon(daemon); + return thread; + } +} diff --git a/src/main/java/tech/brenoepic/at4j/core/thread/ThreadPool.java b/src/main/java/tech/brenoepic/at4j/core/thread/ThreadPool.java index 8ea6319..5503eec 100644 --- a/src/main/java/tech/brenoepic/at4j/core/thread/ThreadPool.java +++ b/src/main/java/tech/brenoepic/at4j/core/thread/ThreadPool.java @@ -7,73 +7,72 @@ import java.util.concurrent.TimeUnit; import java.util.function.Supplier; -/** - * This class creates and contains thread pools which are used by AT4J. - */ +/** This class creates and contains thread pools which are used by AT4J. */ public interface ThreadPool { - /** - * Gets the used executor service. - * - * @return The used executor service. - */ - ExecutorService getExecutorService(); + /** + * Gets the used executor service. + * + * @return The used executor service. + */ + ExecutorService getExecutorService(); - /** - * Gets the used scheduler. - * - * @return The used scheduler. - */ - ScheduledExecutorService getScheduler(); + /** + * Gets the used scheduler. + * + * @return The used scheduler. + */ + ScheduledExecutorService getScheduler(); - /** - * Gets the used daemon scheduler. - * - * @return The used daemon scheduler. - */ - ScheduledExecutorService getDaemonScheduler(); + /** + * Gets the used daemon scheduler. + * + * @return The used daemon scheduler. + */ + ScheduledExecutorService getDaemonScheduler(); - /** - * Gets an executor service which only uses a single thread. - * - * @param threadName The thread name of the executor service. - * Will create a new one if the thread name is used the first time. - * @return The executor service with the given thread name. Never {@code null}! - */ - ExecutorService getSingleThreadExecutorService(String threadName); + /** + * Gets an executor service which only uses a single thread. + * + * @param threadName The thread name of the executor service. Will create a new one if the thread + * name is used the first time. + * @return The executor service with the given thread name. Never {@code null}! + */ + ExecutorService getSingleThreadExecutorService(String threadName); - /** - * Gets an executor service which only uses a single daemon thread. - * - * @param threadName The thread name of the executor service. - * Will create a new one if the thread name is used the first time. - * @return The executor service with the given thread name. Never {@code null}! - */ - ExecutorService getSingleDaemonThreadExecutorService(String threadName); + /** + * Gets an executor service which only uses a single daemon thread. + * + * @param threadName The thread name of the executor service. Will create a new one if the thread + * name is used the first time. + * @return The executor service with the given thread name. Never {@code null}! + */ + ExecutorService getSingleDaemonThreadExecutorService(String threadName); - /** - * Removes an existing executor service. - * - *

This allows you to get a fresh executor service when calling {@link #getSingleThreadExecutorService(String)} - * again. - * - * @param threadName The thread name of the executor service. - * @return The removed and shutdown executor service with the given thread name. - */ - Optional removeAndShutdownSingleThreadExecutorService(String threadName); + /** + * Removes an existing executor service. + * + *

This allows you to get a fresh executor service when calling {@link + * #getSingleThreadExecutorService(String)} again. + * + * @param threadName The thread name of the executor service. + * @return The removed and shutdown executor service with the given thread name. + */ + Optional removeAndShutdownSingleThreadExecutorService(String threadName); - /** - * Executes code after a given duration. - * - *

Tasks will be scheduled on the daemon executor, allowing the bot to shutdown without - * all tasks being executed. This method is not meant to persist scheduled task over - * multiple bot life cycles.

- * - * @param task The code to run. - * @param duration The duration to run the code after. - * @param unit The unit of the duration given. - * @return A future that completes when the scheduled task is finished. - * @param The return type of the future. - */ - CompletableFuture runAfter(Supplier> task, long duration, TimeUnit unit); -} \ No newline at end of file + /** + * Executes code after a given duration. + * + *

Tasks will be scheduled on the daemon executor, allowing the bot to shutdown without all + * tasks being executed. This method is not meant to persist scheduled task over multiple bot life + * cycles. + * + * @param task The code to run. + * @param duration The duration to run the code after. + * @param unit The unit of the duration given. + * @return A future that completes when the scheduled task is finished. + * @param The return type of the future. + */ + CompletableFuture runAfter( + Supplier> task, long duration, TimeUnit unit); +} diff --git a/src/main/java/tech/brenoepic/at4j/core/thread/ThreadPoolImpl.java b/src/main/java/tech/brenoepic/at4j/core/thread/ThreadPoolImpl.java index aa657d8..36d528b 100644 --- a/src/main/java/tech/brenoepic/at4j/core/thread/ThreadPoolImpl.java +++ b/src/main/java/tech/brenoepic/at4j/core/thread/ThreadPoolImpl.java @@ -4,83 +4,109 @@ import java.util.concurrent.*; import java.util.function.Supplier; -/** - * The implementation of {@link ThreadPool}. - */ +/** The implementation of {@link ThreadPool}. */ public class ThreadPoolImpl implements ThreadPool { - private static final int CORE_POOL_SIZE = 1; - private static final int MAXIMUM_POOL_SIZE = Integer.MAX_VALUE; - private static final int KEEP_ALIVE_TIME = 60; - private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; + private static final int CORE_POOL_SIZE = 1; + private static final int MAXIMUM_POOL_SIZE = Integer.MAX_VALUE; + private static final int KEEP_ALIVE_TIME = 60; + private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; - private final ExecutorService executorService = new ThreadPoolExecutor( - CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, TIME_UNIT, new SynchronousQueue<>(), - new AT4JThreadFactory("AT4J - Central ExecutorService - %d", false)); - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool( - CORE_POOL_SIZE, new AT4JThreadFactory("AT4J - Central Scheduler - %d", false)); - private final ScheduledExecutorService daemonScheduler = Executors.newScheduledThreadPool( - CORE_POOL_SIZE, new AT4JThreadFactory("AT4J - Central Daemon Scheduler - %d", true)); - private final ConcurrentHashMap executorServiceSingleThreads = new ConcurrentHashMap<>(); + private final ExecutorService executorService = + new ThreadPoolExecutor( + CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + TIME_UNIT, + new SynchronousQueue<>(), + new AT4JThreadFactory("AT4J - Central ExecutorService - %d", false)); + private final ScheduledExecutorService scheduler = + Executors.newScheduledThreadPool( + CORE_POOL_SIZE, new AT4JThreadFactory("AT4J - Central Scheduler - %d", false)); + private final ScheduledExecutorService daemonScheduler = + Executors.newScheduledThreadPool( + CORE_POOL_SIZE, new AT4JThreadFactory("AT4J - Central Daemon Scheduler - %d", true)); + private final ConcurrentHashMap executorServiceSingleThreads = + new ConcurrentHashMap<>(); - /** - * Shutdowns the thread pool. - */ - public void shutdown() { - executorService.shutdown(); - scheduler.shutdown(); - daemonScheduler.shutdown(); - executorServiceSingleThreads.values().forEach(ExecutorService::shutdown); - } + /** Shutdowns the thread pool. */ + public void shutdown() { + executorService.shutdown(); + scheduler.shutdown(); + daemonScheduler.shutdown(); + executorServiceSingleThreads.values().forEach(ExecutorService::shutdown); + } - @Override - public ExecutorService getExecutorService() { - return executorService; - } + @Override + public ExecutorService getExecutorService() { + return executorService; + } - @Override - public ScheduledExecutorService getScheduler() { - return scheduler; - } + @Override + public ScheduledExecutorService getScheduler() { + return scheduler; + } - @Override - public ScheduledExecutorService getDaemonScheduler() { - return daemonScheduler; - } + @Override + public ScheduledExecutorService getDaemonScheduler() { + return daemonScheduler; + } - @Override - public ExecutorService getSingleThreadExecutorService(String threadName) { - return executorServiceSingleThreads.computeIfAbsent(threadName, key -> - new ThreadPoolExecutor(0, 1, KEEP_ALIVE_TIME, TIME_UNIT, new LinkedBlockingQueue<>(), - new AT4JThreadFactory("AT4J - " + threadName, false))); - } + @Override + public ExecutorService getSingleThreadExecutorService(String threadName) { + return executorServiceSingleThreads.computeIfAbsent( + threadName, + key -> + new ThreadPoolExecutor( + 0, + 1, + KEEP_ALIVE_TIME, + TIME_UNIT, + new LinkedBlockingQueue<>(), + new AT4JThreadFactory("AT4J - " + threadName, false))); + } - @Override - public ExecutorService getSingleDaemonThreadExecutorService(String threadName) { - return executorServiceSingleThreads.computeIfAbsent(threadName, key -> - new ThreadPoolExecutor(0, 1, KEEP_ALIVE_TIME, TIME_UNIT, new LinkedBlockingQueue<>(), - new AT4JThreadFactory("AT4J - " + threadName, true))); - } + @Override + public ExecutorService getSingleDaemonThreadExecutorService(String threadName) { + return executorServiceSingleThreads.computeIfAbsent( + threadName, + key -> + new ThreadPoolExecutor( + 0, + 1, + KEEP_ALIVE_TIME, + TIME_UNIT, + new LinkedBlockingQueue<>(), + new AT4JThreadFactory("AT4J - " + threadName, true))); + } - @Override - public Optional removeAndShutdownSingleThreadExecutorService(String threadName) { - ExecutorService takenExecutorService = executorServiceSingleThreads.remove(threadName); - if (takenExecutorService != null) { - takenExecutorService.shutdown(); - } - return Optional.ofNullable(takenExecutorService); + @Override + public Optional removeAndShutdownSingleThreadExecutorService(String threadName) { + ExecutorService takenExecutorService = executorServiceSingleThreads.remove(threadName); + if (takenExecutorService != null) { + takenExecutorService.shutdown(); } + return Optional.ofNullable(takenExecutorService); + } - @Override - public CompletableFuture runAfter(Supplier> task, long duration, TimeUnit unit) { - CompletableFuture future = new CompletableFuture<>(); - getDaemonScheduler().schedule(() -> task.get().whenComplete((result, ex) -> { - if (ex != null) { - future.completeExceptionally(ex); - } else { - future.complete(result); - } - }), duration, unit); - return future; - } -} \ No newline at end of file + @Override + public CompletableFuture runAfter( + Supplier> task, long duration, TimeUnit unit) { + CompletableFuture future = new CompletableFuture<>(); + getDaemonScheduler() + .schedule( + () -> + task.get() + .whenComplete( + (result, ex) -> { + if (ex != null) { + future.completeExceptionally(ex); + } else { + future.complete(result); + } + }), + duration, + unit); + return future; + } +} diff --git a/src/main/java/tech/brenoepic/at4j/data/DetectedLanguage.java b/src/main/java/tech/brenoepic/at4j/data/DetectedLanguage.java index 8b12247..b0f66d3 100644 --- a/src/main/java/tech/brenoepic/at4j/data/DetectedLanguage.java +++ b/src/main/java/tech/brenoepic/at4j/data/DetectedLanguage.java @@ -2,86 +2,98 @@ import com.fasterxml.jackson.databind.node.ObjectNode; -/** - * Represents a detected language. - */ +/** Represents a detected language. */ public class DetectedLanguage { - private final String languageCode; - private final float score; - private boolean isTranslationSupported = false; - private boolean isTransliterationSupported = false; + private final String languageCode; + private final float score; + private boolean isTranslationSupported = false; + private boolean isTransliterationSupported = false; - public DetectedLanguage(String languageCode, float score, boolean isTranslationSupported, boolean isTransliterationSupported) { - this.languageCode = languageCode; - this.score = score; - this.isTranslationSupported = isTranslationSupported; - this.isTransliterationSupported = isTransliterationSupported; - } + public DetectedLanguage( + String languageCode, + float score, + boolean isTranslationSupported, + boolean isTransliterationSupported) { + this.languageCode = languageCode; + this.score = score; + this.isTranslationSupported = isTranslationSupported; + this.isTransliterationSupported = isTransliterationSupported; + } - public DetectedLanguage(String languageCode, float score) { - this.languageCode = languageCode; - this.score = score; - } + public DetectedLanguage(String languageCode, float score) { + this.languageCode = languageCode; + this.score = score; + } - /** - * Creates a new instance of this class from a json node. - * - * @param jsonNode The json node. - * @return The new instance. - */ - public static DetectedLanguage ofJSON(ObjectNode jsonNode) { - if (jsonNode == null || !jsonNode.has("language") || !jsonNode.has("score")) return null; + /** + * Creates a new instance of this class from a json node. + * + * @param jsonNode The json node. + * @return The new instance. + */ + public static DetectedLanguage ofJSON(ObjectNode jsonNode) { + if (jsonNode == null || !jsonNode.has("language") || !jsonNode.has("score")) return null; - DetectedLanguage detected = new DetectedLanguage(jsonNode.get("language").asText(), jsonNode.get("score").floatValue()); + DetectedLanguage detected = + new DetectedLanguage(jsonNode.get("language").asText(), jsonNode.get("score").floatValue()); - if (jsonNode.has("isTranslationSupported")) - detected.isTranslationSupported = jsonNode.get("isTranslationSupported").asBoolean(); - if (jsonNode.has("isTransliterationSupported")) - detected.isTransliterationSupported = jsonNode.get("isTransliterationSupported").asBoolean(); - return detected; - } + if (jsonNode.has("isTranslationSupported")) + detected.isTranslationSupported = jsonNode.get("isTranslationSupported").asBoolean(); + if (jsonNode.has("isTransliterationSupported")) + detected.isTransliterationSupported = jsonNode.get("isTransliterationSupported").asBoolean(); + return detected; + } - /** - * Gets the detected language code. - * - * @return The detected language code. - */ - public String getLanguageCode() { - return languageCode; - } + /** + * Gets the detected language code. + * + * @return The detected language code. + */ + public String getLanguageCode() { + return languageCode; + } + /** + * Gets A float value indicating the confidence in the result. The score is between zero and + * one, and a low score indicates low confidence. + * + * @return The confidence score of the detected language. + */ + public float getScore() { + return score; + } - /** - * Gets A float value indicating the confidence in the result. The score is between zero and one, and a low score indicates low confidence. - * - * @return The confidence score of the detected language. - */ - public float getScore() { - return score; - } + /** + * Gets a boolean indicating if the language is supported for translation. + * + * @return A boolean indicating if the language is supported for translation. + */ + public boolean isTranslationSupported() { + return isTranslationSupported; + } - /** - * Gets a boolean indicating if the language is supported for translation. - * - * @return A boolean indicating if the language is supported for translation. - */ - public boolean isTranslationSupported() { - return isTranslationSupported; - } + /** + * Gets a boolean indicating if the language is supported for transliteration. + * + * @return A boolean indicating if the language is supported for transliteration. + */ + public boolean isTransliterationSupported() { + return isTransliterationSupported; + } - /** - * Gets a boolean indicating if the language is supported for transliteration. - * - * @return A boolean indicating if the language is supported for transliteration. - */ - - public boolean isTransliterationSupported() { - return isTransliterationSupported; - } - - @Override - public String toString() { - return "DetectedLanguage{" + "language='" + languageCode + '\'' + ", score=" + score + ", isTranslationSupported=" + isTranslationSupported + ", isTransliterationSupported=" + isTransliterationSupported + '}'; - } + @Override + public String toString() { + return "DetectedLanguage{" + + "language='" + + languageCode + + '\'' + + ", score=" + + score + + ", isTranslationSupported=" + + isTranslationSupported + + ", isTransliterationSupported=" + + isTransliterationSupported + + '}'; + } } diff --git a/src/main/java/tech/brenoepic/at4j/data/Translation.java b/src/main/java/tech/brenoepic/at4j/data/Translation.java index c72f120..7a48694 100644 --- a/src/main/java/tech/brenoepic/at4j/data/Translation.java +++ b/src/main/java/tech/brenoepic/at4j/data/Translation.java @@ -2,38 +2,37 @@ import com.fasterxml.jackson.databind.node.ObjectNode; -/** - * A translation of a text. - * This class is immutable. - */ +/** A translation of a text. This class is immutable. */ public class Translation { - private final String languageCode; - private final String text; + private final String languageCode; + private final String text; - public Translation(String languageCode, String value) { - this.languageCode = languageCode; - this.text = value; - } + public Translation(String languageCode, String value) { + this.languageCode = languageCode; + this.text = value; + } - public static Translation from(String languageCode, String value) { - return new Translation(languageCode, value); - } + public static Translation from(String languageCode, String value) { + return new Translation(languageCode, value); + } - public static Translation ofJSON(ObjectNode node) { - if (node == null || !node.has("text") || !node.has("to")) return null; + public static Translation ofJSON(ObjectNode node) { + if (node == null || !node.has("text") || !node.has("to")) return null; - return new Translation(node.get("to").asText(), node.get("text").asText()); - } + return new Translation(node.get("to").asText(), node.get("text").asText()); + } - public String getLanguageCode() { return languageCode; } - public String getText() { return text; } + public String getLanguageCode() { + return languageCode; + } - @Override - public String toString() { - return "Translation{" + - "key='" + languageCode + '\'' + - ", value='" + text + '\'' + - '}'; - } + public String getText() { + return text; + } + + @Override + public String toString() { + return "Translation{" + "key='" + languageCode + '\'' + ", value='" + text + '\'' + '}'; + } } diff --git a/src/main/java/tech/brenoepic/at4j/data/request/AvailableLanguagesParams.java b/src/main/java/tech/brenoepic/at4j/data/request/AvailableLanguagesParams.java index f4759e2..9a81182 100644 --- a/src/main/java/tech/brenoepic/at4j/data/request/AvailableLanguagesParams.java +++ b/src/main/java/tech/brenoepic/at4j/data/request/AvailableLanguagesParams.java @@ -1,30 +1,29 @@ package tech.brenoepic.at4j.data.request; -import tech.brenoepic.at4j.data.request.optional.LanguageScope; - import java.util.Collections; import java.util.List; +import tech.brenoepic.at4j.data.request.optional.LanguageScope; public class AvailableLanguagesParams { - private List scope = List.of(LanguageScope.TRANSLATION); - private String sourceLanguage; + private List scope = List.of(LanguageScope.TRANSLATION); + private String sourceLanguage; - public String getScope() { - return String.join(",", scope.stream().map(LanguageScope::getValue).toArray(String[]::new)); - } + public String getScope() { + return String.join(",", scope.stream().map(LanguageScope::getValue).toArray(String[]::new)); + } - public AvailableLanguagesParams setScope(LanguageScope... scopes) { - this.scope.clear(); - Collections.addAll(this.scope, scopes); - return this; - } + public AvailableLanguagesParams setScope(LanguageScope... scopes) { + this.scope.clear(); + Collections.addAll(this.scope, scopes); + return this; + } - public String getSourceLanguage() { - return sourceLanguage; - } + public String getSourceLanguage() { + return sourceLanguage; + } - public AvailableLanguagesParams setSourceLanguage(String sourceLanguage) { - this.sourceLanguage = sourceLanguage; - return this; - } + public AvailableLanguagesParams setSourceLanguage(String sourceLanguage) { + this.sourceLanguage = sourceLanguage; + return this; + } } diff --git a/src/main/java/tech/brenoepic/at4j/data/request/DetectLanguageParams.java b/src/main/java/tech/brenoepic/at4j/data/request/DetectLanguageParams.java index fd05fff..6c4cf8f 100644 --- a/src/main/java/tech/brenoepic/at4j/data/request/DetectLanguageParams.java +++ b/src/main/java/tech/brenoepic/at4j/data/request/DetectLanguageParams.java @@ -1,29 +1,26 @@ package tech.brenoepic.at4j.data.request; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; public class DetectLanguageParams { - private final String text; + private final String text; - public DetectLanguageParams(String text) { - this.text = text; - } + public DetectLanguageParams(String text) { + this.text = text; + } + public String getText() { + return text; + } - public String getText() { - return text; - } + public ArrayNode getBody() { + if (text == null || text.isEmpty()) return null; - public ArrayNode getBody() { - if (text == null || text.isEmpty()) return null; - - ObjectNode textNode = JsonNodeFactory.instance.objectNode(); - textNode.put("Text", text); - return JsonNodeFactory.instance.arrayNode().add(textNode); - - } + ObjectNode textNode = JsonNodeFactory.instance.objectNode(); + textNode.put("Text", text); + return JsonNodeFactory.instance.arrayNode().add(textNode); + } } diff --git a/src/main/java/tech/brenoepic/at4j/data/request/TranslateParams.java b/src/main/java/tech/brenoepic/at4j/data/request/TranslateParams.java index 2285ce4..bb43e5b 100644 --- a/src/main/java/tech/brenoepic/at4j/data/request/TranslateParams.java +++ b/src/main/java/tech/brenoepic/at4j/data/request/TranslateParams.java @@ -4,197 +4,210 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; +import java.util.*; +import java.util.stream.Collectors; import tech.brenoepic.at4j.azure.lang.Language; import tech.brenoepic.at4j.data.request.optional.ProfanityAction; import tech.brenoepic.at4j.data.request.optional.ProfanityMarker; import tech.brenoepic.at4j.data.request.optional.TextType; -import java.util.*; -import java.util.stream.Collectors; - public class TranslateParams { - private String text; - private TextType textType; - private ProfanityAction profanityAction; - private ProfanityMarker profanityMarker; - private Boolean includeAlignment; - private Boolean includeSentenceLength; - private String sourceLanguage; - private Collection targetLanguages; - private String suggestedFromLanguage; - - public TranslateParams(String text) { - this.text = text; - } - - public TranslateParams setText(String text) { - this.text = text; - return this; - } - - - /** - * Defines whether the text being translated is plain text or HTML text. Any HTML needs to be a well-formed, complete element. - * @param textType Possible values are: plain (default) or html. - * @return This instance. - */ - public TranslateParams setTextType(TextType textType) { - this.textType = textType; - return this; - } - - - /** - * Specifies how profanities should be treated in translations. - * - * @param profanityAction Possible values are: Marked, Deleted or NoAction (default). - * @return This instance. - * @see Handle profanity - */ - public TranslateParams setProfanityAction(ProfanityAction profanityAction) { - this.profanityAction = profanityAction; - return this; - } - - /** - * Specifies how profanities should be marked in translations. - * - * @param profanityMarker Possible values are: Asterisk (default) or Tag. To understand ways to treat profanity. - * @return This instance. - * @see Profanity Handling - */ - public TranslateParams setProfanityMarker(ProfanityMarker profanityMarker) { - this.profanityMarker = profanityMarker; - return this; - } - - /** - * Specifies whether to include the alignment string in the response. The alignment string is a string of alphanumeric pairs separated by spaces. - * Each pair indicates the start and end of the corresponding word in the translated text. - * @param includeAlignment Specifies whether to include the alignment string in the response. - * @return This instance. - */ - public TranslateParams setIncludeAlignment(Boolean includeAlignment) { - this.includeAlignment = includeAlignment; - return this; - } - - /** - * Specifies whether to include the number of characters in each translated sentence. - * @param includeSentenceLength Specifies whether to include the number of characters in each translated sentence. - * @return This instance. - */ - public TranslateParams setIncludeSentenceLength(Boolean includeSentenceLength) { - this.includeSentenceLength = includeSentenceLength; - return this; - } - - public String getSuggestedFromLanguage() { - return suggestedFromLanguage; - } - - /** - * Specifies a fallback language if the language of the input text can't be identified. - *
- * Language autodetection is applied when the from parameter is omitted. If detection fails, the `suggestedFrom` language is assumed - * @param suggestedFromLanguage A string representing the language code of the translation text. - * @return This instance. - */ - public TranslateParams setSuggestedFromLanguage(String suggestedFromLanguage) { - this.suggestedFromLanguage = suggestedFromLanguage; - return this; + private String text; + private TextType textType; + private ProfanityAction profanityAction; + private ProfanityMarker profanityMarker; + private Boolean includeAlignment; + private Boolean includeSentenceLength; + private String sourceLanguage; + private Collection targetLanguages; + private String suggestedFromLanguage; + + public TranslateParams(String text) { + this.text = text; + } + + public TranslateParams setText(String text) { + this.text = text; + return this; + } + + /** + * Defines whether the text being translated is plain text or HTML text. Any HTML needs to be a + * well-formed, complete element. + * + * @param textType Possible values are: plain (default) or html. + * @return This instance. + */ + public TranslateParams setTextType(TextType textType) { + this.textType = textType; + return this; + } + + /** + * Specifies how profanities should be treated in translations. + * + * @param profanityAction Possible values are: Marked, Deleted or NoAction (default). + * @return This instance. + * @see Handle + * profanity + */ + public TranslateParams setProfanityAction(ProfanityAction profanityAction) { + this.profanityAction = profanityAction; + return this; + } + + /** + * Specifies how profanities should be marked in translations. + * + * @param profanityMarker Possible values are: Asterisk (default) or Tag. To understand ways to + * treat profanity. + * @return This instance. + * @see Profanity + * Handling + */ + public TranslateParams setProfanityMarker(ProfanityMarker profanityMarker) { + this.profanityMarker = profanityMarker; + return this; + } + + /** + * Specifies whether to include the alignment string in the response. The alignment string is a + * string of alphanumeric pairs separated by spaces. Each pair indicates the start and end of the + * corresponding word in the translated text. + * + * @param includeAlignment Specifies whether to include the alignment string in the response. + * @return This instance. + */ + public TranslateParams setIncludeAlignment(Boolean includeAlignment) { + this.includeAlignment = includeAlignment; + return this; + } + + /** + * Specifies whether to include the number of characters in each translated sentence. + * + * @param includeSentenceLength Specifies whether to include the number of characters in each + * translated sentence. + * @return This instance. + */ + public TranslateParams setIncludeSentenceLength(Boolean includeSentenceLength) { + this.includeSentenceLength = includeSentenceLength; + return this; + } + + public String getSuggestedFromLanguage() { + return suggestedFromLanguage; + } + + /** + * Specifies a fallback language if the language of the input text can't be identified.
+ * Language autodetection is applied when the from parameter is omitted. If detection fails, the + * `suggestedFrom` language is assumed + * + * @param suggestedFromLanguage A string representing the language code of the translation text. + * @return This instance. + */ + public TranslateParams setSuggestedFromLanguage(String suggestedFromLanguage) { + this.suggestedFromLanguage = suggestedFromLanguage; + return this; + } + + public TranslateParams setSourceLanguage(Language sourceLanguage) { + this.sourceLanguage = sourceLanguage.getCode(); + return this; + } + + public TranslateParams setSourceLanguage(String sourceLanguage) { + this.sourceLanguage = sourceLanguage; + return this; + } + + public TranslateParams setTargetLanguages(Collection targetLanguages) { + this.targetLanguages = + Collections.unmodifiableCollection( + targetLanguages.stream() + .map(Language::getCode) + .collect(Collectors.toCollection(ArrayList::new))); + return this; + } + + public TranslateParams setTargetLanguages(String... targetLanguages) { + this.targetLanguages = List.of(targetLanguages); + return this; + } + + public String getText() { + return text; + } + + public Boolean getIncludeAlignment() { + return includeAlignment; + } + + public Boolean getIncludeSentenceLength() { + return includeSentenceLength; + } + + public TextType getTextType() { + return textType; + } + + public ProfanityAction getProfanityAction() { + return profanityAction; + } + + public ProfanityMarker getProfanityMarker() { + return profanityMarker; + } + + public String getSourceLanguage() { + return sourceLanguage; + } + + public Collection getTargetLanguages() { + return targetLanguages; + } + + public Map getQueryParameters() { + Map params = new HashMap<>(); + if (getSourceLanguage() != null) { + params.put("from", getSourceLanguage()); + } + + if (getTextType() != null) { + params.put("textType", getTextType().getValue()); + } + + if (getProfanityAction() != null) { + params.put("profanityAction", getProfanityAction().getValue()); + if (getProfanityMarker() != null) + params.put("profanityMarker", getProfanityMarker().getValue()); + } + + if (getIncludeAlignment() != null) { + params.put("includeAlignment", getIncludeAlignment().toString()); + } + + if (getIncludeSentenceLength() != null) { + params.put("includeSentenceLength", getIncludeSentenceLength().toString()); } - public TranslateParams setSourceLanguage(Language sourceLanguage) { - this.sourceLanguage = sourceLanguage.getCode(); - return this; + if (getSuggestedFromLanguage() != null) { + params.put("suggestedFrom", getSuggestedFromLanguage()); } - public TranslateParams setSourceLanguage(String sourceLanguage) { - this.sourceLanguage = sourceLanguage; - return this; - } - - public TranslateParams setTargetLanguages(Collection targetLanguages) { - this.targetLanguages = Collections.unmodifiableCollection(targetLanguages.stream().map(Language::getCode).collect(Collectors.toCollection(ArrayList::new))); - return this; - } - - public TranslateParams setTargetLanguages(String... targetLanguages) { - this.targetLanguages = List.of(targetLanguages); - return this; - } - - public String getText() { - return text; - } - - public Boolean getIncludeAlignment() { - return includeAlignment; - } - - public Boolean getIncludeSentenceLength() { - return includeSentenceLength; - } - - public TextType getTextType() { - return textType; - } - - public ProfanityAction getProfanityAction() { - return profanityAction; - } - - public ProfanityMarker getProfanityMarker() { - return profanityMarker; - } - - public String getSourceLanguage() { - return sourceLanguage; - } - - public Collection getTargetLanguages() { - return targetLanguages; - } - - public Map getQueryParameters() { - Map params = new HashMap<>(); - if (getSourceLanguage() != null) { - params.put("from", getSourceLanguage()); - } - - if (getTextType() != null) { - params.put("textType", getTextType().getValue()); - } - - if (getProfanityAction() != null) { - params.put("profanityAction", getProfanityAction().getValue()); - if (getProfanityMarker() != null) - params.put("profanityMarker", getProfanityMarker().getValue()); - } - - if (getIncludeAlignment() != null) { - params.put("includeAlignment", getIncludeAlignment().toString()); - } - - if (getIncludeSentenceLength() != null) { - params.put("includeSentenceLength", getIncludeSentenceLength().toString()); - } - - if(getSuggestedFromLanguage() != null) { - params.put("suggestedFrom", getSuggestedFromLanguage()); - } - - return params; - } + return params; + } - public JsonNode getBody() { - ArrayNode body = JsonNodeFactory.instance.arrayNode(); - if (getText() != null && !getText().isEmpty()) { - ObjectNode textNode = JsonNodeFactory.instance.objectNode(); - textNode.put("Text", getText()); - body.add(textNode); - } - return body; + public JsonNode getBody() { + ArrayNode body = JsonNodeFactory.instance.arrayNode(); + if (getText() != null && !getText().isEmpty()) { + ObjectNode textNode = JsonNodeFactory.instance.objectNode(); + textNode.put("Text", getText()); + body.add(textNode); } -} \ No newline at end of file + return body; + } +} diff --git a/src/main/java/tech/brenoepic/at4j/data/request/optional/LanguageScope.java b/src/main/java/tech/brenoepic/at4j/data/request/optional/LanguageScope.java index 4e83806..61a793a 100644 --- a/src/main/java/tech/brenoepic/at4j/data/request/optional/LanguageScope.java +++ b/src/main/java/tech/brenoepic/at4j/data/request/optional/LanguageScope.java @@ -1,25 +1,23 @@ package tech.brenoepic.at4j.data.request.optional; /** - * A comma-separated list of names defining the group of languages to return. - *
- * Allowed group names are: translation, transliteration, and dictionary. - *
- * If no scope is given, then all groups are returned, which is equivalent to passing scope=translation,transliteration,dictionary. + * A comma-separated list of names defining the group of languages to return.
+ * Allowed group names are: translation, transliteration, and dictionary.
+ * If no scope is given, then all groups are returned, which is equivalent to passing + * scope=translation,transliteration,dictionary. */ public enum LanguageScope { + TRANSLATION("translation"), + TRANSLITERATION("transliteration"), + DICTIONARY("dictionary"); - TRANSLATION("translation"), - TRANSLITERATION("transliteration"), - DICTIONARY("dictionary"); + private final String value; - private final String value; - LanguageScope(String value) { - this.value = value; - } - - public String getValue() { - return value; - } + LanguageScope(String value) { + this.value = value; + } + public String getValue() { + return value; + } } diff --git a/src/main/java/tech/brenoepic/at4j/data/request/optional/ProfanityAction.java b/src/main/java/tech/brenoepic/at4j/data/request/optional/ProfanityAction.java index 19b78e9..c02514a 100644 --- a/src/main/java/tech/brenoepic/at4j/data/request/optional/ProfanityAction.java +++ b/src/main/java/tech/brenoepic/at4j/data/request/optional/ProfanityAction.java @@ -1,22 +1,25 @@ package tech.brenoepic.at4j.data.request.optional; /** - * Specifies how profanities should be treated in translations. - *
+ * Specifies how profanities should be treated in translations.
* Possible values are: Marked, Deleted or NoAction (default). - * @see Handle profanity + * + * @see Handle + * profanity */ public enum ProfanityAction { - MARKED("Marked"), - DELETED("Deleted"), - NO_ACTION("NoAction"); + MARKED("Marked"), + DELETED("Deleted"), + NO_ACTION("NoAction"); - private final String value; - ProfanityAction(String value) { - this.value = value; - } + private final String value; - public String getValue() { - return value; - } + ProfanityAction(String value) { + this.value = value; + } + + public String getValue() { + return value; + } } diff --git a/src/main/java/tech/brenoepic/at4j/data/request/optional/ProfanityMarker.java b/src/main/java/tech/brenoepic/at4j/data/request/optional/ProfanityMarker.java index 3c63da8..527fe4c 100644 --- a/src/main/java/tech/brenoepic/at4j/data/request/optional/ProfanityMarker.java +++ b/src/main/java/tech/brenoepic/at4j/data/request/optional/ProfanityMarker.java @@ -1,20 +1,24 @@ package tech.brenoepic.at4j.data.request.optional; /** - * Specifies how profanities should be marked in translations. - * Possible values are: Asterisk (default) or Tag. To understand ways to treat profanity. - * @see Profanity Handling + * Specifies how profanities should be marked in translations. Possible values are: Asterisk + * (default) or Tag. To understand ways to treat profanity. + * + * @see Profanity + * Handling */ public enum ProfanityMarker { - ASTERISK("Asterisk"), - TAG("Tag"); + ASTERISK("Asterisk"), + TAG("Tag"); - private final String value; - ProfanityMarker(String value) { - this.value = value; - } + private final String value; - public String getValue() { - return value; - } + ProfanityMarker(String value) { + this.value = value; + } + + public String getValue() { + return value; + } } diff --git a/src/main/java/tech/brenoepic/at4j/data/request/optional/TextType.java b/src/main/java/tech/brenoepic/at4j/data/request/optional/TextType.java index 575420b..4b15a68 100644 --- a/src/main/java/tech/brenoepic/at4j/data/request/optional/TextType.java +++ b/src/main/java/tech/brenoepic/at4j/data/request/optional/TextType.java @@ -1,19 +1,21 @@ package tech.brenoepic.at4j.data.request.optional; + /** - * Defines whether the text being translated is plain text or HTML text. Any HTML needs to be a well-formed, complete element. - *
+ * Defines whether the text being translated is plain text or HTML text. Any HTML needs to be a + * well-formed, complete element.
* Possible values are: plain (default) or html. */ public enum TextType { - PLAIN("plain"), - HTML("html"); + PLAIN("plain"), + HTML("html"); + + private final String value; - private final String value; - TextType(String value) { - this.value = value; - } + TextType(String value) { + this.value = value; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/src/main/java/tech/brenoepic/at4j/data/response/TranslationResponse.java b/src/main/java/tech/brenoepic/at4j/data/response/TranslationResponse.java index 6f2f122..18361af 100644 --- a/src/main/java/tech/brenoepic/at4j/data/response/TranslationResponse.java +++ b/src/main/java/tech/brenoepic/at4j/data/response/TranslationResponse.java @@ -1,36 +1,35 @@ package tech.brenoepic.at4j.data.response; +import java.util.Collection; +import javax.annotation.Nullable; import tech.brenoepic.at4j.data.DetectedLanguage; import tech.brenoepic.at4j.data.Translation; -import javax.annotation.Nullable; -import java.util.Collection; - public class TranslationResponse { - @Nullable - private DetectedLanguage detectedLanguage = null; - private final Collection translations; + @Nullable private DetectedLanguage detectedLanguage = null; + private final Collection translations; - public TranslationResponse(@Nullable DetectedLanguage detectedLanguage, Collection translations) { - this.detectedLanguage = detectedLanguage; - this.translations = translations; - } + public TranslationResponse( + @Nullable DetectedLanguage detectedLanguage, Collection translations) { + this.detectedLanguage = detectedLanguage; + this.translations = translations; + } - public TranslationResponse(Collection translations) { - this.translations = translations; - } + public TranslationResponse(Collection translations) { + this.translations = translations; + } + public void setDetectedLanguage(@Nullable DetectedLanguage detectedLanguage) { + this.detectedLanguage = detectedLanguage; + } - public void setDetectedLanguage(@Nullable DetectedLanguage detectedLanguage) { - this.detectedLanguage = detectedLanguage; - } + @Nullable + public DetectedLanguage getDetectedLanguage() { + return detectedLanguage; + } - @Nullable - public DetectedLanguage getDetectedLanguage() { - return detectedLanguage; - } - public Collection getTranslations() { - return translations; - } + public Collection getTranslations() { + return translations; + } } diff --git a/src/main/java/tech/brenoepic/at4j/util/logging/FallbackLoggerConfiguration.java b/src/main/java/tech/brenoepic/at4j/util/logging/FallbackLoggerConfiguration.java index c0ebe49..4369a32 100644 --- a/src/main/java/tech/brenoepic/at4j/util/logging/FallbackLoggerConfiguration.java +++ b/src/main/java/tech/brenoepic/at4j/util/logging/FallbackLoggerConfiguration.java @@ -2,61 +2,58 @@ import java.util.concurrent.atomic.AtomicBoolean; -/** - * This class can be used to configure AT4J's fallback logger. - */ +/** This class can be used to configure AT4J's fallback logger. */ public class FallbackLoggerConfiguration { - private static final AtomicBoolean debug = new AtomicBoolean(); - - private static final AtomicBoolean trace = new AtomicBoolean(); - - private FallbackLoggerConfiguration() { - throw new UnsupportedOperationException(); - } - - /** - * Checks whether debug logging is enabled. - * - * @return Whether debug logging is enabled or not. - */ - public static boolean isDebugEnabled() { - return debug.get(); - } - - /** - * Sets whether debug logging should be enabled. - * Disabling debug logging automatically disables trace logging, too. - * - * @param debug Whether debug logging should be enabled or not. - */ - public static void setDebug(boolean debug) { - FallbackLoggerConfiguration.debug.set(debug); - if (!debug) { - trace.set(false); - } + private static final AtomicBoolean debug = new AtomicBoolean(); + + private static final AtomicBoolean trace = new AtomicBoolean(); + + private FallbackLoggerConfiguration() { + throw new UnsupportedOperationException(); + } + + /** + * Checks whether debug logging is enabled. + * + * @return Whether debug logging is enabled or not. + */ + public static boolean isDebugEnabled() { + return debug.get(); + } + + /** + * Sets whether debug logging should be enabled. Disabling debug logging automatically disables + * trace logging, too. + * + * @param debug Whether debug logging should be enabled or not. + */ + public static void setDebug(boolean debug) { + FallbackLoggerConfiguration.debug.set(debug); + if (!debug) { + trace.set(false); } - - /** - * Checks whether trace logging is enabled. - * - * @return Whether trace logging is enabled or not. - */ - public static boolean isTraceEnabled() { - return trace.get(); + } + + /** + * Checks whether trace logging is enabled. + * + * @return Whether trace logging is enabled or not. + */ + public static boolean isTraceEnabled() { + return trace.get(); + } + + /** + * Sets whether trace logging should be enabled. Enabling trace logging automatically enables + * debug logging, too. + * + * @param trace Whether trace logging should be enabled or not. + */ + public static void setTrace(boolean trace) { + FallbackLoggerConfiguration.trace.set(trace); + if (trace) { + debug.set(true); } - - /** - * Sets whether trace logging should be enabled. - * Enabling trace logging automatically enables debug logging, too. - * - * @param trace Whether trace logging should be enabled or not. - */ - public static void setTrace(boolean trace) { - FallbackLoggerConfiguration.trace.set(trace); - if (trace) { - debug.set(true); - } - } - -} \ No newline at end of file + } +} diff --git a/src/main/java/tech/brenoepic/at4j/util/logging/LoggerUtil.java b/src/main/java/tech/brenoepic/at4j/util/logging/LoggerUtil.java index 4aebdd1..6527236 100644 --- a/src/main/java/tech/brenoepic/at4j/util/logging/LoggerUtil.java +++ b/src/main/java/tech/brenoepic/at4j/util/logging/LoggerUtil.java @@ -1,6 +1,10 @@ package tech.brenoepic.at4j.util.logging; - +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -8,63 +12,70 @@ import org.apache.logging.log4j.util.PropertiesUtil; import org.apache.logging.log4j.util.ProviderUtil; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -/** - * This class is used to get a {@link Logger} instance. - */ +/** This class is used to get a {@link Logger} instance. */ public class LoggerUtil { - LoggerUtil() { - throw new UnsupportedOperationException(); - } + LoggerUtil() { + throw new UnsupportedOperationException(); + } - private static final AtomicReference initialized = new AtomicReference<>(false); - private static final AtomicBoolean noLogger = new AtomicBoolean(); - private static final Map loggers = new ConcurrentHashMap<>(); + private static final AtomicReference initialized = new AtomicReference<>(false); + private static final AtomicBoolean noLogger = new AtomicBoolean(); + private static final Map loggers = new ConcurrentHashMap<>(); - /** - * Get or create a logger with the given name. - * - * @param name The name of the logger. - * @return The logger with the given name. - */ - public static Logger getLogger(String name) { - AtomicBoolean logWarning = new AtomicBoolean(false); - initialized.updateAndGet(initialized -> { - if (Boolean.TRUE.equals(!initialized) && !ProviderUtil.hasProviders()) { - noLogger.set(true); - logWarning.set(true); - } - return true; + /** + * Get or create a logger with the given name. + * + * @param name The name of the logger. + * @return The logger with the given name. + */ + public static Logger getLogger(String name) { + AtomicBoolean logWarning = new AtomicBoolean(false); + initialized.updateAndGet( + initialized -> { + if (Boolean.TRUE.equals(!initialized) && !ProviderUtil.hasProviders()) { + noLogger.set(true); + logWarning.set(true); + } + return true; }); - if (noLogger.get()) { - return loggers.computeIfAbsent(name, key -> { - Level debugLevel = FallbackLoggerConfiguration.isDebugEnabled() ? Level.DEBUG : Level.INFO; - Level level = FallbackLoggerConfiguration.isTraceEnabled() ? Level.TRACE : debugLevel; - Logger logger = new SimpleLogger(name, level, true, false, true, true, "yyyy-MM-dd HH:mm:ss.SSSZ", null, new PropertiesUtil(new Properties()), System.out); - if (logWarning.get()) { - logger.info("No Log4j2 compatible logger was found. Using default AT4J implementation!"); - } - return new PrivacyProtectionLogger(logger); - }); - } else { - return new PrivacyProtectionLogger(LogManager.getLogger(name)); - } - } - - /** - * Gets or creates a logger for the given name. - * - * @param clazz The class of the logger. - * @return A logger for the given class. - */ - public static Logger getLogger(Class clazz) { - return getLogger(clazz.getName()); + if (noLogger.get()) { + return loggers.computeIfAbsent( + name, + key -> { + Level debugLevel = + FallbackLoggerConfiguration.isDebugEnabled() ? Level.DEBUG : Level.INFO; + Level level = FallbackLoggerConfiguration.isTraceEnabled() ? Level.TRACE : debugLevel; + Logger logger = + new SimpleLogger( + name, + level, + true, + false, + true, + true, + "yyyy-MM-dd HH:mm:ss.SSSZ", + null, + new PropertiesUtil(new Properties()), + System.out); + if (logWarning.get()) { + logger.info( + "No Log4j2 compatible logger was found. Using default AT4J implementation!"); + } + return new PrivacyProtectionLogger(logger); + }); + } else { + return new PrivacyProtectionLogger(LogManager.getLogger(name)); } + } -} \ No newline at end of file + /** + * Gets or creates a logger for the given name. + * + * @param clazz The class of the logger. + * @return A logger for the given class. + */ + public static Logger getLogger(Class clazz) { + return getLogger(clazz.getName()); + } +} diff --git a/src/main/java/tech/brenoepic/at4j/util/logging/PrivacyProtectionLogger.java b/src/main/java/tech/brenoepic/at4j/util/logging/PrivacyProtectionLogger.java index 6dd2705..530aa60 100644 --- a/src/main/java/tech/brenoepic/at4j/util/logging/PrivacyProtectionLogger.java +++ b/src/main/java/tech/brenoepic/at4j/util/logging/PrivacyProtectionLogger.java @@ -1,150 +1,213 @@ package tech.brenoepic.at4j.util.logging; +import java.util.HashSet; +import java.util.Set; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.spi.AbstractLogger; -import java.util.HashSet; -import java.util.Set; - /** * This logger is used to wrap another logger and replace configured sensitive data by asterisks. */ public class PrivacyProtectionLogger extends AbstractLogger { - private static final String PRIVATE_DATA_REPLACEMENT = "**********"; - private static final Set privateDataSet = new HashSet<>(); - - private final Logger delegate; - - /** - * Class constructor. - * It's recommended to use {@link LoggerUtil#getLogger(String)}. - * - * @param delegate The delegate logger that gets the cleaned messages. - */ - PrivacyProtectionLogger(Logger delegate) { - this.delegate = delegate; - } - - /** - * Adds private data to be asterisked out in log messages. - * A {@code null} argument is simply ignored. - * - * @param privateData The private data. - */ - public static void addPrivateData(String privateData) { - if (privateData != null && !privateData.trim().isEmpty()) { - privateDataSet.add(privateData); - } - } - - @Override - public void logMessage(String fqcn, Level level, Marker marker, Message message, Throwable t) { - String formattedMessage = message.getFormattedMessage(); - if (privateDataSet.stream().anyMatch(formattedMessage::contains)) { - delegate.log(level, marker, privateDataSet.stream().reduce( - formattedMessage, (s, privateData) -> s.replace(privateData, PRIVATE_DATA_REPLACEMENT)), t); - } else { - delegate.log(level, marker, message, t); - } - } - - @Override - public boolean isEnabled(Level level, Marker marker, Message message, Throwable t) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, CharSequence message, Throwable t) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, Object message, Throwable t) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Throwable t) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object... params) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, - Object p4) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, - Object p4, Object p5) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, - Object p4, Object p5, Object p6) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, - Object p4, Object p5, Object p6, Object p7) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, - Object p4, Object p5, Object p6, Object p7, Object p8) { - return delegate.isEnabled(level, marker); - } - - @Override - public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, - Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) { - return delegate.isEnabled(level, marker); - } - - @Override - public Level getLevel() { - return delegate.getLevel(); - } - - @Override - public String getName() { - return delegate.getName(); - } + private static final String PRIVATE_DATA_REPLACEMENT = "**********"; + private static final Set privateDataSet = new HashSet<>(); + + private final Logger delegate; + + /** + * Class constructor. It's recommended to use {@link LoggerUtil#getLogger(String)}. + * + * @param delegate The delegate logger that gets the cleaned messages. + */ + PrivacyProtectionLogger(Logger delegate) { + this.delegate = delegate; + } + + /** + * Adds private data to be asterisked out in log messages. A {@code null} argument is simply + * ignored. + * + * @param privateData The private data. + */ + public static void addPrivateData(String privateData) { + if (privateData != null && !privateData.trim().isEmpty()) { + privateDataSet.add(privateData); + } + } + + @Override + public void logMessage(String fqcn, Level level, Marker marker, Message message, Throwable t) { + String formattedMessage = message.getFormattedMessage(); + if (privateDataSet.stream().anyMatch(formattedMessage::contains)) { + delegate.log( + level, + marker, + privateDataSet.stream() + .reduce( + formattedMessage, + (s, privateData) -> s.replace(privateData, PRIVATE_DATA_REPLACEMENT)), + t); + } else { + delegate.log(level, marker, message, t); + } + } + + @Override + public boolean isEnabled(Level level, Marker marker, Message message, Throwable t) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled(Level level, Marker marker, CharSequence message, Throwable t) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled(Level level, Marker marker, Object message, Throwable t) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled(Level level, Marker marker, String message, Throwable t) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled(Level level, Marker marker, String message) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled(Level level, Marker marker, String message, Object... params) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled(Level level, Marker marker, String message, Object p0) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled( + Level level, Marker marker, String message, Object p0, Object p1, Object p2) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled( + Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled( + Level level, + Marker marker, + String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled( + Level level, + Marker marker, + String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled( + Level level, + Marker marker, + String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled( + Level level, + Marker marker, + String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled( + Level level, + Marker marker, + String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8) { + return delegate.isEnabled(level, marker); + } + + @Override + public boolean isEnabled( + Level level, + Marker marker, + String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9) { + return delegate.isEnabled(level, marker); + } + + @Override + public Level getLevel() { + return delegate.getLevel(); + } + + @Override + public String getName() { + return delegate.getName(); + } } diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestEndpoint.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestEndpoint.java index dd686ff..06402e7 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestEndpoint.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestEndpoint.java @@ -1,90 +1,84 @@ package tech.brenoepic.at4j.util.rest; +import java.util.Optional; import okhttp3.HttpUrl; import tech.brenoepic.at4j.azure.BaseURL; -import java.util.Optional; - -/** - * This enum contains all endpoints that we may use. - */ +/** This enum contains all endpoints that we may use. */ public enum RestEndpoint { + TRANSLATE("/translate"), + LANGUAGES("/languages"), + DETECT("/detect"); - TRANSLATE("/translate"), - LANGUAGES("/languages"), - DETECT("/detect"); + /** The endpoint url (only including the base, not the BaseURL). */ + private final String endpointUrl; - /** - * The endpoint url (only including the base, not the BaseURL). - */ - private final String endpointUrl; + /** + * The position of the major parameter starting with 0 or -1 if no major + * parameter exists. + */ + private final int majorParameterPosition; - /** - * The position of the major parameter starting with 0 or -1 if no major parameter exists. - */ - private final int majorParameterPosition; + RestEndpoint(String endpointUrl) { + this(endpointUrl, -1); + } - RestEndpoint(String endpointUrl) { - this(endpointUrl, -1); - } + RestEndpoint(String endpointUrl, int majorParameterPosition) { + this.endpointUrl = endpointUrl; + this.majorParameterPosition = majorParameterPosition; + } - RestEndpoint(String endpointUrl, int majorParameterPosition) { - this.endpointUrl = endpointUrl; - this.majorParameterPosition = majorParameterPosition; + /** + * Gets the major parameter position of the endpoint. The position starts counting at 0 + * ! + * + * @return An optional which is present if the endpoint has a major parameter. + */ + public Optional getMajorParameterPosition() { + if (majorParameterPosition >= 0) { + return Optional.of(majorParameterPosition); } + return Optional.empty(); + } - /** - * Gets the major parameter position of the endpoint. - * The position starts counting at 0! - * - * @return An optional which is present if the endpoint has a major parameter. - */ - public Optional getMajorParameterPosition() { - if (majorParameterPosition >= 0) { - return Optional.of(majorParameterPosition); - } - return Optional.empty(); - } + /** + * Gets the endpoint url (only including the base, not the BaseURL). + * + * @return The gateway url. + */ + public String getEndpointUrl() { + return endpointUrl; + } - /** - * Gets the endpoint url (only including the base, not the BaseURL). - * - * @return The gateway url. - */ - public String getEndpointUrl() { - return endpointUrl; - } - - /** - * Gets the full url of the endpoint. - * Parameters which are "too much" are added to the end. - * - * @param parameters The parameters of the url. E.g., for channel ids. - * @return The full url of the endpoint. - */ - public String getFullUrl(BaseURL baseURL, String... parameters) { - StringBuilder url = new StringBuilder("https://" + baseURL.getUrl() + getEndpointUrl()); + /** + * Gets the full url of the endpoint. Parameters which are "too much" are added to the end. + * + * @param parameters The parameters of the url. E.g., for channel ids. + * @return The full url of the endpoint. + */ + public String getFullUrl(BaseURL baseURL, String... parameters) { + StringBuilder url = new StringBuilder("https://" + baseURL.getUrl() + getEndpointUrl()); - url = new StringBuilder(String.format(url.toString(), (Object[]) parameters)); - int parameterAmount = getEndpointUrl().split("%s").length - (getEndpointUrl().endsWith("%s") ? 0 : 1); - - if (parameters.length > parameterAmount) { - for (int i = parameterAmount; i < parameters.length; i++) { - url.append("/").append(parameters[i]); - } - } - return url.toString(); - } + url = new StringBuilder(String.format(url.toString(), (Object[]) parameters)); + int parameterAmount = + getEndpointUrl().split("%s").length - (getEndpointUrl().endsWith("%s") ? 0 : 1); - /** - * Gets the full {@link HttpUrl http url} of the endpoint. - * Parameters which are "too much" are added to the end. - * - * @param parameters The parameters of the url. E.g., for channel ids. - * @return The full http url of the endpoint. - */ - public HttpUrl getOkHttpUrl(BaseURL baseURL, String... parameters) { - return HttpUrl.parse(getFullUrl(baseURL, parameters)); + if (parameters.length > parameterAmount) { + for (int i = parameterAmount; i < parameters.length; i++) { + url.append("/").append(parameters[i]); + } } + return url.toString(); + } + /** + * Gets the full {@link HttpUrl http url} of the endpoint. Parameters which are "too much" are + * added to the end. + * + * @param parameters The parameters of the url. E.g., for channel ids. + * @return The full http url of the endpoint. + */ + public HttpUrl getOkHttpUrl(BaseURL baseURL, String... parameters) { + return HttpUrl.parse(getFullUrl(baseURL, parameters)); + } } diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestMethod.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestMethod.java index e6210da..7b6527d 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestMethod.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestMethod.java @@ -1,14 +1,10 @@ package tech.brenoepic.at4j.util.rest; -/** - * An enum with all commonly used http methods. - */ +/** An enum with all commonly used http methods. */ public enum RestMethod { - - GET, - POST, - PUT, - DELETE, - PATCH - + GET, + POST, + PUT, + DELETE, + PATCH } diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequest.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequest.java index 1945899..0cf6644 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequest.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequest.java @@ -3,14 +3,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; -import okhttp3.*; -import org.apache.logging.log4j.Logger; -import tech.brenoepic.at4j.AT4J; -import tech.brenoepic.at4j.AzureApi; -import tech.brenoepic.at4j.core.AzureApiImpl; -import tech.brenoepic.at4j.core.exceptions.AzureException; -import tech.brenoepic.at4j.util.logging.LoggerUtil; - import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -19,380 +11,432 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Function; +import okhttp3.*; +import org.apache.logging.log4j.Logger; +import tech.brenoepic.at4j.AT4J; +import tech.brenoepic.at4j.AzureApi; +import tech.brenoepic.at4j.core.AzureApiImpl; +import tech.brenoepic.at4j.core.exceptions.AzureException; +import tech.brenoepic.at4j.util.logging.LoggerUtil; -/** - * This class is used to wrap a rest request. - */ +/** This class is used to wrap a rest request. */ public class RestRequest { - /** - * The (logger) of this class. - */ - private static final Logger logger = LoggerUtil.getLogger(RestRequest.class); - - private final AzureApiImpl api; - private final RestMethod method; - private final RestEndpoint endpoint; - - private volatile boolean includeAuthorizationHeader = true; - private volatile String[] urlParameters = new String[0]; - private final Multimap queryParameters = ArrayListMultimap.create(); - private final Map headers = new HashMap<>(); - private volatile String body = null; - - private final CompletableFuture result = new CompletableFuture<>(); - - /** - * The multipart body of the request. - */ - private MultipartBody multipartBody; - - /** - * The custom major parameter if it's not included in the url (e.g., for reactions) - */ - private String customMajorParam = null; - - /** - * The origin of the rest request. - */ - private final Exception origin; - - /** - * Creates a new instance of this class. - * - * @param api The api which will be used to execute the request. - * @param method The http method of the request. - * @param endpoint The endpoint to which the request should be sent. - */ - public RestRequest(AzureApi api, RestMethod method, RestEndpoint endpoint) { - this.api = (AzureApiImpl) api; - this.method = method; - this.endpoint = endpoint; - this.queryParameters.put("api-version", AT4J.AZURE_TRANSLATOR_API_VERSION); - - this.origin = new Exception("origin of RestRequest call"); - } - - /** - * Gets the api which is used for this request. - * - * @return The api which is used for this request. - */ - public AzureApiImpl getApi() { - return api; - } - - /** - * Gets the method of this request. - * - * @return The method of this request. - */ - public RestMethod getMethod() { - return method; - } - - /** - * Gets the endpoint of this request. - * - * @return The endpoint of this request. - */ - public RestEndpoint getEndpoint() { - return endpoint; - } - - /** - * Gets the query parameters of this request. - * - * @return The query parameters of this request. - */ - - public Multimap getQueryParameters() { - return queryParameters; - } - - /** - * Gets an array with all used url parameters. - * - * @return An array with all used url parameters. - */ - public String[] getUrlParameters() { - return urlParameters; - } - - /** - * Gets the body of this request. - * - * @return The body of this request. - */ - public Optional getBody() { - return Optional.ofNullable(body); + /** The (logger) of this class. */ + private static final Logger logger = LoggerUtil.getLogger(RestRequest.class); + + private final AzureApiImpl api; + private final RestMethod method; + private final RestEndpoint endpoint; + + private volatile boolean includeAuthorizationHeader = true; + private volatile String[] urlParameters = new String[0]; + private final Multimap queryParameters = ArrayListMultimap.create(); + private final Map headers = new HashMap<>(); + private volatile String body = null; + + private final CompletableFuture result = new CompletableFuture<>(); + + /** The multipart body of the request. */ + private MultipartBody multipartBody; + + /** The custom major parameter if it's not included in the url (e.g., for reactions) */ + private String customMajorParam = null; + + /** The origin of the rest request. */ + private final Exception origin; + + /** + * Creates a new instance of this class. + * + * @param api The api which will be used to execute the request. + * @param method The http method of the request. + * @param endpoint The endpoint to which the request should be sent. + */ + public RestRequest(AzureApi api, RestMethod method, RestEndpoint endpoint) { + this.api = (AzureApiImpl) api; + this.method = method; + this.endpoint = endpoint; + this.queryParameters.put("api-version", AT4J.AZURE_TRANSLATOR_API_VERSION); + + this.origin = new Exception("origin of RestRequest call"); + } + + /** + * Gets the api which is used for this request. + * + * @return The api which is used for this request. + */ + public AzureApiImpl getApi() { + return api; + } + + /** + * Gets the method of this request. + * + * @return The method of this request. + */ + public RestMethod getMethod() { + return method; + } + + /** + * Gets the endpoint of this request. + * + * @return The endpoint of this request. + */ + public RestEndpoint getEndpoint() { + return endpoint; + } + + /** + * Gets the query parameters of this request. + * + * @return The query parameters of this request. + */ + public Multimap getQueryParameters() { + return queryParameters; + } + + /** + * Gets an array with all used url parameters. + * + * @return An array with all used url parameters. + */ + public String[] getUrlParameters() { + return urlParameters; + } + + /** + * Gets the body of this request. + * + * @return The body of this request. + */ + public Optional getBody() { + return Optional.ofNullable(body); + } + + /** + * Gets the major url parameter of this request. If a request has a major parameter, it means that + * the rate-limits for this request are based on this parameter. + * + * @return The major url parameter used for rate-limits. + */ + public Optional getMajorUrlParameter() { + if (customMajorParam != null) { + return Optional.of(customMajorParam); } - /** - * Gets the major url parameter of this request. - * If a request has a major parameter, it means that the rate-limits for this request are based on this parameter. - * - * @return The major url parameter used for rate-limits. - */ - public Optional getMajorUrlParameter() { - if (customMajorParam != null) { - return Optional.of(customMajorParam); - } - - Optional majorParameterPosition = endpoint.getMajorParameterPosition(); - if (!majorParameterPosition.isPresent()) { - return Optional.empty(); - } - - if (majorParameterPosition.get() >= urlParameters.length) { - return Optional.empty(); - } - - return Optional.of(urlParameters[majorParameterPosition.get()]); + Optional majorParameterPosition = endpoint.getMajorParameterPosition(); + if (!majorParameterPosition.isPresent()) { + return Optional.empty(); } - /** - * Gets the origin of the rest request. - * - * @return The origin of the rest request. - */ - public Exception getOrigin() { - return origin; + if (majorParameterPosition.get() >= urlParameters.length) { + return Optional.empty(); } - /** - * Adds a query parameter to the url. - * - * @param key The key of the parameter. - * @param value The value of the parameter. - * @return The current instance to chain call methods. - */ - public RestRequest addQueryParameter(String key, String value) { - queryParameters.put(key, value); - return this; - } - - /** - * Adds a header to the request. - * - * @param name The name of the header. - * @param value The value of the header. - * @return The current instance to chain call methods. - */ - public RestRequest addHeader(String name, String value) { - headers.put(name, value); - return this; - } - - - /** - * Sets the url parameters, e.g., a language parameter. - * - * @param parameters The parameters. - * @return The current instance to chain call methods. - */ - public RestRequest setUrlParameters(String... parameters) { - this.urlParameters = parameters; - return this; - } - - /** - * Sets the multipart body of the request. - * If a multipart body is set, the {@link #setBody(String)} method is ignored! - * - * @param multipartBody The multipart body of the request. - * @return The current instance to chain call methods. - */ - public RestRequest setMultipartBody(MultipartBody multipartBody) { - this.multipartBody = multipartBody; - return this; - } - - /** - * Sets a custom major parameter. - * - * @param customMajorParam The custom parameter to set. - * @return The current instance to chain call methods. - */ - public RestRequest setCustomMajorParam(String customMajorParam) { - this.customMajorParam = customMajorParam; - return this; - } - - /** - * Sets the body of the request. - * - * @param body The body of the request. - * @return The current instance to chain call methods. - */ - public RestRequest setBody(JsonNode body) { - return setBody(body.toString()); - } - - /** - * Sets the body of the request. - * - * @param body The body of the request. - * @return The current instance to chain call methods. - */ - public RestRequest setBody(String body) { - this.body = body; - return this; - } - - /** - * Sets if an authorization header should be included in this request. - * - * @param includeAuthorizationHeader Whether the authorization header should be included or not. - * @return The current instance to chain call methods. - */ - public RestRequest includeAuthorizationHeader(boolean includeAuthorizationHeader) { - this.includeAuthorizationHeader = includeAuthorizationHeader; - return this; - } - - - /** - * Executes the request. This will automatically retry if we hit a ratelimit. - * - * @param function A function which processes the rest response to the requested object. - * @return A future which will contain the output of the function. - */ - public CompletableFuture execute(Function function) { - api.getRatelimitManager().queueRequest(this); - CompletableFuture future = new CompletableFuture<>(); - result.whenComplete((result, throwable) -> { - if (throwable != null) { - future.completeExceptionally(throwable); - return; - } - try { - future.complete(function.apply(result)); - } catch (Throwable t) { - future.completeExceptionally(t); - } + return Optional.of(urlParameters[majorParameterPosition.get()]); + } + + /** + * Gets the origin of the rest request. + * + * @return The origin of the rest request. + */ + public Exception getOrigin() { + return origin; + } + + /** + * Adds a query parameter to the url. + * + * @param key The key of the parameter. + * @param value The value of the parameter. + * @return The current instance to chain call methods. + */ + public RestRequest addQueryParameter(String key, String value) { + queryParameters.put(key, value); + return this; + } + + /** + * Adds a header to the request. + * + * @param name The name of the header. + * @param value The value of the header. + * @return The current instance to chain call methods. + */ + public RestRequest addHeader(String name, String value) { + headers.put(name, value); + return this; + } + + /** + * Sets the url parameters, e.g., a language parameter. + * + * @param parameters The parameters. + * @return The current instance to chain call methods. + */ + public RestRequest setUrlParameters(String... parameters) { + this.urlParameters = parameters; + return this; + } + + /** + * Sets the multipart body of the request. If a multipart body is set, the {@link + * #setBody(String)} method is ignored! + * + * @param multipartBody The multipart body of the request. + * @return The current instance to chain call methods. + */ + public RestRequest setMultipartBody(MultipartBody multipartBody) { + this.multipartBody = multipartBody; + return this; + } + + /** + * Sets a custom major parameter. + * + * @param customMajorParam The custom parameter to set. + * @return The current instance to chain call methods. + */ + public RestRequest setCustomMajorParam(String customMajorParam) { + this.customMajorParam = customMajorParam; + return this; + } + + /** + * Sets the body of the request. + * + * @param body The body of the request. + * @return The current instance to chain call methods. + */ + public RestRequest setBody(JsonNode body) { + return setBody(body.toString()); + } + + /** + * Sets the body of the request. + * + * @param body The body of the request. + * @return The current instance to chain call methods. + */ + public RestRequest setBody(String body) { + this.body = body; + return this; + } + + /** + * Sets if an authorization header should be included in this request. + * + * @param includeAuthorizationHeader Whether the authorization header should be included or not. + * @return The current instance to chain call methods. + */ + public RestRequest includeAuthorizationHeader(boolean includeAuthorizationHeader) { + this.includeAuthorizationHeader = includeAuthorizationHeader; + return this; + } + + /** + * Executes the request. This will automatically retry if we hit a ratelimit. + * + * @param function A function which processes the rest response to the requested object. + * @return A future which will contain the output of the function. + */ + public CompletableFuture execute(Function function) { + api.getRatelimitManager().queueRequest(this); + CompletableFuture future = new CompletableFuture<>(); + result.whenComplete( + (result, throwable) -> { + if (throwable != null) { + future.completeExceptionally(throwable); + return; + } + try { + future.complete(function.apply(result)); + } catch (Throwable t) { + future.completeExceptionally(t); + } }); - return future; + return future; + } + + /** + * Gets the result of this request. This will not start executing, return the result! + * + * @return Gets the result of this request. + */ + public CompletableFuture getResult() { + return result; + } + + /** + * Gets the information for this rest request. + * + * @return The information for this rest request. + */ + public RestRequestInformation asRestRequestInformation() { + try { + return new RestRequestInformationImpl( + api, + new URL(endpoint.getFullUrl(api.getBaseURL(), urlParameters)), + queryParameters, + headers, + body); + } catch (MalformedURLException e) { + throw new AssertionError(e); } - - /** - * Gets the result of this request. This will not start executing, return the result! - * - * @return Gets the result of this request. - */ - public CompletableFuture getResult() { - return result; + } + + /** + * Executes the request blocking. + * + * @return The result of the request. + * @throws AzureException or IOException Thrown if something goes wrong. + */ + public RestRequestResult executeBlocking() throws AzureException, IOException { + Request.Builder requestBuilder = new Request.Builder(); + HttpUrl.Builder httpUrlBuilder = + endpoint.getOkHttpUrl(api.getBaseURL(), urlParameters).newBuilder(); + queryParameters.forEach(httpUrlBuilder::addQueryParameter); + requestBuilder.url(httpUrlBuilder.build()); + request(requestBuilder); + + if (includeAuthorizationHeader) { + requestBuilder.addHeader("Ocp-Apim-Subscription-Key", api.getSubscriptionKey()); + api.getSubscriptionRegion() + .ifPresent(region -> requestBuilder.addHeader("Ocp-Apim-Subscription-Region", region)); } - /** - * Gets the information for this rest request. - * - * @return The information for this rest request. - */ - public RestRequestInformation asRestRequestInformation() { - try { - return new RestRequestInformationImpl(api, new URL(endpoint.getFullUrl(api.getBaseURL(), urlParameters)), queryParameters, headers, body); - } catch (MalformedURLException e) { - throw new AssertionError(e); - } + headers.forEach(requestBuilder::addHeader); + logger.debug( + "Trying to send {} request to {}{}", + method::name, + () -> endpoint.getFullUrl(api.getBaseURL(), urlParameters), + () -> body != null ? " with body " + body : ""); + + try (Response response = getApi().getHttpClient().newCall(requestBuilder.build()).execute()) { + RestRequestResult requestResult = new RestRequestResult(this, response); + logger.debug( + "Sent {} request to {} and received status code {} with{} body{}", + method::name, + () -> endpoint.getFullUrl(api.getBaseURL(), urlParameters), + response::code, + () -> requestResult.getBody().map(b -> "").orElse(" empty"), + () -> requestResult.getStringBody().map(s -> " " + s).orElse("")); + + if (response.code() >= 300 || response.code() < 200) { + return handleError(response.code(), requestResult); + } + + return requestResult; } - - /** - * Executes the request blocking. - * - * @return The result of the request. - * @throws AzureException or IOException Thrown if something goes wrong. - */ - public RestRequestResult executeBlocking() throws AzureException, IOException { - Request.Builder requestBuilder = new Request.Builder(); - HttpUrl.Builder httpUrlBuilder = endpoint.getOkHttpUrl(api.getBaseURL(), urlParameters).newBuilder(); - queryParameters.forEach(httpUrlBuilder::addQueryParameter); - requestBuilder.url(httpUrlBuilder.build()); - request(requestBuilder); - - if (includeAuthorizationHeader) { - requestBuilder.addHeader("Ocp-Apim-Subscription-Key", api.getSubscriptionKey()); - api.getSubscriptionRegion().ifPresent(region -> requestBuilder.addHeader("Ocp-Apim-Subscription-Region", region)); - } - - headers.forEach(requestBuilder::addHeader); - logger.debug("Trying to send {} request to {}{}", method::name, () -> endpoint.getFullUrl(api.getBaseURL(), urlParameters), () -> body != null ? " with body " + body : ""); - - try (Response response = getApi().getHttpClient().newCall(requestBuilder.build()).execute()) { - RestRequestResult requestResult = new RestRequestResult(this, response); - logger.debug("Sent {} request to {} and received status code {} with{} body{}", method::name, () -> endpoint.getFullUrl(api.getBaseURL(), urlParameters), response::code, () -> requestResult.getBody().map(b -> "").orElse(" empty"), () -> requestResult.getStringBody().map(s -> " " + s).orElse("")); - - if (response.code() >= 300 || response.code() < 200) { - return handleError(response.code(), requestResult); - } - - return requestResult; - } + } + + private RestRequestResult handleError(int resultCode, RestRequestResult result) + throws AzureException { + RestRequestInformation requestInformation = asRestRequestInformation(); + RestRequestResponseInformation responseInformation = + new RestRequestResponseInformationImpl(requestInformation, result); + Optional responseCode = + RestRequestHttpResponseCode.fromCode(resultCode); + + if (!result.getJsonBody().isNull() && result.getJsonBody().has("error")) { + handleKnownError(result, responseCode.orElse(null), requestInformation, responseInformation); } - private RestRequestResult handleError(int resultCode, RestRequestResult result) throws AzureException { - RestRequestInformation requestInformation = asRestRequestInformation(); - RestRequestResponseInformation responseInformation = new RestRequestResponseInformationImpl(requestInformation, result); - Optional responseCode = RestRequestHttpResponseCode.fromCode(resultCode); - - if (!result.getJsonBody().isNull() && result.getJsonBody().has("error")) { - handleKnownError(result, responseCode.orElse(null), requestInformation, responseInformation); - } - - if (resultCode == 429) { - return result; - } - - Optional azureException = responseCode.flatMap(restRequestHttpResponseCode -> restRequestHttpResponseCode.getAzureException(origin, "Received a " + resultCode + " response from Azure with" + (result.getBody().isPresent() ? "" : " empty") + " body" + result.getStringBody().map(s -> " " + s).orElse("") + "!", requestInformation, responseInformation)); - - String bodyPresent = result.getBody().isPresent() ? "" : " empty"; - throw azureException.isPresent() ? azureException.get() : new AzureException(origin, "Received a " + resultCode + " response from Azure with" + bodyPresent + " body" + result.getStringBody().map(s -> " " + s).orElse("") + "!", requestInformation, responseInformation); + if (resultCode == 429) { + return result; } - private void handleKnownError(RestRequestResult result, RestRequestHttpResponseCode responseCode, RestRequestInformation requestInformation, RestRequestResponseInformation responseInformation) throws AzureException { - JsonNode errorBody = result.getJsonBody().get("error"); - int code = errorBody.get("code").asInt(); - String message = errorBody.has("message") ? errorBody.get("message").asText() : null; - Optional azureException = RestRequestResultErrorCode.fromCode(code, responseCode).flatMap(restRequestResultCode -> restRequestResultCode.getAzureException(origin, (message == null) ? restRequestResultCode.getMeaning() : message, requestInformation, responseInformation)); - - if (azureException.isPresent()) { - throw azureException.get(); - } + Optional azureException = + responseCode.flatMap( + restRequestHttpResponseCode -> + restRequestHttpResponseCode.getAzureException( + origin, + "Received a " + + resultCode + + " response from Azure with" + + (result.getBody().isPresent() ? "" : " empty") + + " body" + + result.getStringBody().map(s -> " " + s).orElse("") + + "!", + requestInformation, + responseInformation)); + + String bodyPresent = result.getBody().isPresent() ? "" : " empty"; + throw azureException.isPresent() + ? azureException.get() + : new AzureException( + origin, + "Received a " + + resultCode + + " response from Azure with" + + bodyPresent + + " body" + + result.getStringBody().map(s -> " " + s).orElse("") + + "!", + requestInformation, + responseInformation); + } + + private void handleKnownError( + RestRequestResult result, + RestRequestHttpResponseCode responseCode, + RestRequestInformation requestInformation, + RestRequestResponseInformation responseInformation) + throws AzureException { + JsonNode errorBody = result.getJsonBody().get("error"); + int code = errorBody.get("code").asInt(); + String message = errorBody.has("message") ? errorBody.get("message").asText() : null; + Optional azureException = + RestRequestResultErrorCode.fromCode(code, responseCode) + .flatMap( + restRequestResultCode -> + restRequestResultCode.getAzureException( + origin, + (message == null) ? restRequestResultCode.getMeaning() : message, + requestInformation, + responseInformation)); + + if (azureException.isPresent()) { + throw azureException.get(); } + } - private RequestBody createMultipartBody() { - if (multipartBody != null) { - return multipartBody; - } - - if (body != null) { - return RequestBody.create(body, MediaType.parse("application/json")); - } - return RequestBody.create(new byte[0], null); + private RequestBody createMultipartBody() { + if (multipartBody != null) { + return multipartBody; } - private void request(okhttp3.Request.Builder requestBuilder) { - RequestBody requestBody = createMultipartBody(); - - switch (method) { - case GET: - requestBuilder.get(); - break; - case POST: - requestBuilder.post(requestBody); - break; - case PUT: - requestBuilder.put(requestBody); - break; - case DELETE: - requestBuilder.delete(requestBody); - break; - case PATCH: - requestBuilder.patch(requestBody); - break; - default: - throw new IllegalArgumentException("Unsupported http method!"); - } + if (body != null) { + return RequestBody.create(body, MediaType.parse("application/json")); } - -} \ No newline at end of file + return RequestBody.create(new byte[0], null); + } + + private void request(okhttp3.Request.Builder requestBuilder) { + RequestBody requestBody = createMultipartBody(); + + switch (method) { + case GET: + requestBuilder.get(); + break; + case POST: + requestBuilder.post(requestBody); + break; + case PUT: + requestBuilder.put(requestBody); + break; + case DELETE: + requestBuilder.delete(requestBody); + break; + case PATCH: + requestBuilder.patch(requestBody); + break; + default: + throw new IllegalArgumentException("Unsupported http method!"); + } + } +} diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestHttpResponseCode.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestHttpResponseCode.java index 963674b..d284632 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestHttpResponseCode.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestHttpResponseCode.java @@ -1,250 +1,226 @@ package tech.brenoepic.at4j.util.rest; -import tech.brenoepic.at4j.core.exceptions.BadRequestException; -import tech.brenoepic.at4j.core.exceptions.AzureException; -import tech.brenoepic.at4j.core.exceptions.NotFoundException; -import tech.brenoepic.at4j.core.exceptions.AzureExceptionInstantiator; - import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; +import tech.brenoepic.at4j.core.exceptions.AzureException; +import tech.brenoepic.at4j.core.exceptions.AzureExceptionInstantiator; +import tech.brenoepic.at4j.core.exceptions.BadRequestException; +import tech.brenoepic.at4j.core.exceptions.NotFoundException; /** - * An enum with all rest request result codes as defined by - * Azure. + * An enum with all rest request result codes as defined by Azure. */ public enum RestRequestHttpResponseCode { - /** - * The request completed successfully. - */ - OK(200, "The request completed successfully"), - - /** - * The entity was created successfully. - */ - CREATED(201, "The entity was created successfully"), - - /** - * The request completed successfully but returned no content. - */ - NO_CONTENT(204, "The request completed successfully but returned no content"), - - /** - * The entity was not modified (no action was taken). - */ - NOT_MODIFIED(304, "The entity was not modified (no action was taken)"), - - /** - * The request was improperly formatted, or the server couldn't understand it. - */ - BAD_REQUEST(400, "The request was improperly formatted, or the server couldn't understand it", - BadRequestException::new, BadRequestException.class), - - /** - * The Authorization header was missing or invalid. - */ - UNAUTHORIZED(401, "The Authorization header was missing or invalid"), - - /** - * The Authorization token you passed did not have permission to the resource. - */ - FORBIDDEN(403, "The Authorization token you passed did not have permission to the resource"), - - /** - * The resource at the location specified doesn't exist. - */ - NOT_FOUND(404, "The resource at the location specified doesn't exist", - NotFoundException::new, NotFoundException.class), - - /** - * The HTTP method used is not valid for the location specified. - */ - METHOD_NOT_ALLOWED(405, "The HTTP method used is not valid for the location specified"), - - /** - * The request timed out, you can retry it again later with the same parameters. - */ - REQUEST_TIMEOUT(408, "The request timed out, you can retry it again later"), - - /** - * The request entity has a media type which the server or resource does not support. - */ - UNSUPPORTED_MEDIA_TYPE(415, "The request entity has a media type which the server or resource does not support"), - /** - * You've made too many requests. - * - */ - TOO_MANY_REQUESTS(429, "You've made too many requests"), - - /** - * There was not a gateway available to process your request. Wait a bit and retry. - */ - GATEWAY_UNAVAILABLE(502, "There was not a gateway available to process your request. Wait a bit and retry"), - - /** - * There was an internal server error while processing your request. - */ - INTERNAL_SERVER_ERROR(500, "There was an internal server error while processing your request"), - - /** - * There was a service unavailable while processing your request. - */ - SERVICE_UNAVAILABLE(503, "There was a service unavailable while processing your request"); - - /** - * A map for retrieving the enum instances by code. - */ - private static final Map instanceByCode; - - /** - * A map for retrieving the enum instances by exception class. - */ - private static final Map, RestRequestHttpResponseCode> instanceByExceptionClass; - - /** - * The actual numeric result code. - */ - private final int code; - - /** - * The textual meaning. - */ - private final String meaning; - - /** - * The azure exception instantiated that produces instances to throw for this kind of result code. - */ - private final AzureExceptionInstantiator azureExceptionInstantiator; - - /** - * The azure exception class to throw for this kind of result code. - */ - private final Class azureExceptionClass; - - static { - instanceByCode = Collections.unmodifiableMap( - Arrays.stream(values()) - .collect(Collectors.toMap(RestRequestHttpResponseCode::getCode, Function.identity()))); - - instanceByExceptionClass = Collections.unmodifiableMap( - Arrays.stream(values()) - .filter(restRequestHttpResponseCode -> - restRequestHttpResponseCode.getAzureExceptionClass().isPresent()) - .collect(Collectors.toMap(restRequestHttpResponseCode -> - restRequestHttpResponseCode.getAzureExceptionClass() - .orElse(null), - Function.identity()))); - } - - /** - * Creates a new rest request http response code. - * - * @param code The actual numeric response code. - * @param meaning The textual meaning. - */ - RestRequestHttpResponseCode(int code, String meaning) { - this(code, meaning, null, null); + /** The request completed successfully. */ + OK(200, "The request completed successfully"), + + /** The entity was created successfully. */ + CREATED(201, "The entity was created successfully"), + + /** The request completed successfully but returned no content. */ + NO_CONTENT(204, "The request completed successfully but returned no content"), + + /** The entity was not modified (no action was taken). */ + NOT_MODIFIED(304, "The entity was not modified (no action was taken)"), + + /** The request was improperly formatted, or the server couldn't understand it. */ + BAD_REQUEST( + 400, + "The request was improperly formatted, or the server couldn't understand it", + BadRequestException::new, + BadRequestException.class), + + /** The Authorization header was missing or invalid. */ + UNAUTHORIZED(401, "The Authorization header was missing or invalid"), + + /** The Authorization token you passed did not have permission to the resource. */ + FORBIDDEN(403, "The Authorization token you passed did not have permission to the resource"), + + /** The resource at the location specified doesn't exist. */ + NOT_FOUND( + 404, + "The resource at the location specified doesn't exist", + NotFoundException::new, + NotFoundException.class), + + /** The HTTP method used is not valid for the location specified. */ + METHOD_NOT_ALLOWED(405, "The HTTP method used is not valid for the location specified"), + + /** The request timed out, you can retry it again later with the same parameters. */ + REQUEST_TIMEOUT(408, "The request timed out, you can retry it again later"), + + /** The request entity has a media type which the server or resource does not support. */ + UNSUPPORTED_MEDIA_TYPE( + 415, "The request entity has a media type which the server or resource does not support"), + /** You've made too many requests. */ + TOO_MANY_REQUESTS(429, "You've made too many requests"), + + /** There was not a gateway available to process your request. Wait a bit and retry. */ + GATEWAY_UNAVAILABLE( + 502, "There was not a gateway available to process your request. Wait a bit and retry"), + + /** There was an internal server error while processing your request. */ + INTERNAL_SERVER_ERROR(500, "There was an internal server error while processing your request"), + + /** There was a service unavailable while processing your request. */ + SERVICE_UNAVAILABLE(503, "There was a service unavailable while processing your request"); + + /** A map for retrieving the enum instances by code. */ + private static final Map instanceByCode; + + /** A map for retrieving the enum instances by exception class. */ + private static final Map, RestRequestHttpResponseCode> + instanceByExceptionClass; + + /** The actual numeric result code. */ + private final int code; + + /** The textual meaning. */ + private final String meaning; + + /** + * The azure exception instantiated that produces instances to throw for this kind of result code. + */ + private final AzureExceptionInstantiator azureExceptionInstantiator; + + /** The azure exception class to throw for this kind of result code. */ + private final Class azureExceptionClass; + + static { + instanceByCode = + Collections.unmodifiableMap( + Arrays.stream(values()) + .collect( + Collectors.toMap(RestRequestHttpResponseCode::getCode, Function.identity()))); + + instanceByExceptionClass = + Collections.unmodifiableMap( + Arrays.stream(values()) + .filter( + restRequestHttpResponseCode -> + restRequestHttpResponseCode.getAzureExceptionClass().isPresent()) + .collect( + Collectors.toMap( + restRequestHttpResponseCode -> + restRequestHttpResponseCode.getAzureExceptionClass().orElse(null), + Function.identity()))); + } + + /** + * Creates a new rest request http response code. + * + * @param code The actual numeric response code. + * @param meaning The textual meaning. + */ + RestRequestHttpResponseCode(int code, String meaning) { + this(code, meaning, null, null); + } + + /** + * Creates a new rest request http response code. + * + * @param code The actual numeric response code. + * @param meaning The textual meaning. + * @param AzureExceptionInstantiator The azure exception instantiator that produces instances to + * throw for this kind of result code. + */ + RestRequestHttpResponseCode( + int code, + String meaning, + AzureExceptionInstantiator AzureExceptionInstantiator, + Class AzureExceptionClass) { + this.code = code; + this.meaning = meaning; + this.azureExceptionInstantiator = AzureExceptionInstantiator; + this.azureExceptionClass = AzureExceptionClass; + + if ((AzureExceptionInstantiator == null) && (AzureExceptionClass != null) + || (AzureExceptionInstantiator != null) && (AzureExceptionClass == null)) { + + throw new IllegalArgumentException( + "AzureExceptionInstantiator and AzureExceptionClass do not match"); } - - /** - * Creates a new rest request http response code. - * - * @param code The actual numeric response code. - * @param meaning The textual meaning. - * @param AzureExceptionInstantiator The azure exception instantiator that produces - * instances to throw for this kind of result code. - */ - RestRequestHttpResponseCode( - int code, String meaning, - AzureExceptionInstantiator AzureExceptionInstantiator, Class AzureExceptionClass) { - this.code = code; - this.meaning = meaning; - this.azureExceptionInstantiator = AzureExceptionInstantiator; - this.azureExceptionClass = AzureExceptionClass; - - if ((AzureExceptionInstantiator == null) && (AzureExceptionClass != null) - || (AzureExceptionInstantiator != null) && (AzureExceptionClass == null)) { - - throw new IllegalArgumentException("AzureExceptionInstantiator and AzureExceptionClass do not match"); - } + } + + /** + * Gets the rest request http response code by actual numeric response code. + * + * @param code The actual numeric response code. + * @return The rest request http response code with the actual numeric response code. + */ + public static Optional fromCode(int code) { + return Optional.ofNullable(instanceByCode.get(code)); + } + + /** + * Gets the rest request http response code by azure exception class. If no entry for the given + * class is found, the parents are checked until match is found or {@code AzureException} is + * reached. + * + * @param AzureExceptionClass The azure exception class. + * @return The rest request http response code with the azure exception class. + */ + @SuppressWarnings("unchecked") + public static Optional fromAzureExceptionClass( + Class AzureExceptionClass) { + Class clazz = AzureExceptionClass; + while (instanceByExceptionClass.get(clazz) == null) { + if (clazz == AzureException.class) { + return Optional.empty(); + } + clazz = (Class) clazz.getSuperclass(); } - - /** - * Gets the rest request http response code by actual numeric response code. - * - * @param code The actual numeric response code. - * @return The rest request http response code with the actual numeric response code. - */ - public static Optional fromCode(int code) { - return Optional.ofNullable(instanceByCode.get(code)); - } - - /** - * Gets the rest request http response code by azure exception class. - * If no entry for the given class is found, the parents are checked until match is found or - * {@code AzureException} is reached. - * - * @param AzureExceptionClass The azure exception class. - * @return The rest request http response code with the azure exception class. - */ - @SuppressWarnings("unchecked") - public static Optional fromAzureExceptionClass( - Class AzureExceptionClass) { - Class clazz = AzureExceptionClass; - while (instanceByExceptionClass.get(clazz) == null) { - if (clazz == AzureException.class) { - return Optional.empty(); - } - clazz = (Class) clazz.getSuperclass(); - } - return Optional.of(instanceByExceptionClass.get(clazz)); - } - - /** - * Gets the actual numeric response code. - * - * @return The actual numeric response code. - */ - public int getCode() { - return code; - } - - /** - * Gets the textual meaning. - * - * @return The textual meaning. - */ - public String getMeaning() { - return meaning; - } - - /** - * Gets the azure exception to throw for this kind of result code. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - * @return The azure exception to throw for this kind of result code. - */ - public Optional getAzureException(Exception origin, String message, - RestRequestInformation request, - RestRequestResponseInformation response) { - return Optional.ofNullable(azureExceptionInstantiator) - .map(instantiator -> instantiator.createInstance(origin, message, request, response)); - } - - /** - * Gets the azure exception class to throw for this kind of result code. - * - * @return The azure exception class to throw for this kind of result code. - */ - public Optional> getAzureExceptionClass() { - return Optional.ofNullable(azureExceptionClass); - } - + return Optional.of(instanceByExceptionClass.get(clazz)); + } + + /** + * Gets the actual numeric response code. + * + * @return The actual numeric response code. + */ + public int getCode() { + return code; + } + + /** + * Gets the textual meaning. + * + * @return The textual meaning. + */ + public String getMeaning() { + return meaning; + } + + /** + * Gets the azure exception to throw for this kind of result code. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + * @return The azure exception to throw for this kind of result code. + */ + public Optional getAzureException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + return Optional.ofNullable(azureExceptionInstantiator) + .map(instantiator -> instantiator.createInstance(origin, message, request, response)); + } + + /** + * Gets the azure exception class to throw for this kind of result code. + * + * @return The azure exception class to throw for this kind of result code. + */ + public Optional> getAzureExceptionClass() { + return Optional.ofNullable(azureExceptionClass); + } } diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestInformation.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestInformation.java index 5f869e1..40d9baa 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestInformation.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestInformation.java @@ -1,51 +1,46 @@ package tech.brenoepic.at4j.util.rest; import com.google.common.collect.Multimap; -import tech.brenoepic.at4j.AzureApi; - import java.net.URL; import java.util.Map; import java.util.Optional; +import tech.brenoepic.at4j.AzureApi; -/** - * Some information about a rest request. - */ +/** Some information about a rest request. */ public interface RestRequestInformation { - /** - * Gets the azure api instance which created the request. - * - * @return The responsible azure api instance. - */ - AzureApi getApi(); - - /** - * Gets the url, the request should be sent to. - * - * @return The url, the request should be sent to. - */ - URL getUrl(); - - /** - * Gets the query parameters of the rest request. - * - * @return The query parameters of the rest request. - */ - - Multimap getQueryParameters(); - - /** - * Gets the headers of the rest request. - * - * @return The headers of the rest request. - */ - Map getHeaders(); - - /** - * Gets the body of the rest request as string. - * - * @return The body of the rest request. - */ - Optional getBody(); - -} \ No newline at end of file + /** + * Gets the azure api instance which created the request. + * + * @return The responsible azure api instance. + */ + AzureApi getApi(); + + /** + * Gets the url, the request should be sent to. + * + * @return The url, the request should be sent to. + */ + URL getUrl(); + + /** + * Gets the query parameters of the rest request. + * + * @return The query parameters of the rest request. + */ + Multimap getQueryParameters(); + + /** + * Gets the headers of the rest request. + * + * @return The headers of the rest request. + */ + Map getHeaders(); + + /** + * Gets the body of the rest request as string. + * + * @return The body of the rest request. + */ + Optional getBody(); +} diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestInformationImpl.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestInformationImpl.java index 96f99a8..60312c1 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestInformationImpl.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestInformationImpl.java @@ -2,68 +2,65 @@ import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; -import tech.brenoepic.at4j.AzureApi; - import java.net.URL; import java.util.Collections; import java.util.Map; import java.util.Optional; +import tech.brenoepic.at4j.AzureApi; -/** - * The implementation of {@link RestRequestInformation}. - */ +/** The implementation of {@link RestRequestInformation}. */ public class RestRequestInformationImpl implements RestRequestInformation { - private final AzureApi api; - private final URL url; - private final - Multimap queryParameters; - private final Map headers; - private final String body; - - /** - * Creates new rest request information. - * - * @param api The responsible azure api instance. - * @param url The url, the request should be sent to. - * @param queryParameter The query parameters of the rest request. - * @param headers The headers of the rest request. - * @param body The body of the rest request. - */ - public RestRequestInformationImpl(AzureApi api, URL url, - Multimap queryParameter, - Map headers, String body) { - this.api = api; - this.url = url; - this.queryParameters = queryParameter; - this.headers = headers; - this.body = body; - } + private final AzureApi api; + private final URL url; + private final Multimap queryParameters; + private final Map headers; + private final String body; - @Override - public AzureApi getApi() { - return api; - } + /** + * Creates new rest request information. + * + * @param api The responsible azure api instance. + * @param url The url, the request should be sent to. + * @param queryParameter The query parameters of the rest request. + * @param headers The headers of the rest request. + * @param body The body of the rest request. + */ + public RestRequestInformationImpl( + AzureApi api, + URL url, + Multimap queryParameter, + Map headers, + String body) { + this.api = api; + this.url = url; + this.queryParameters = queryParameter; + this.headers = headers; + this.body = body; + } - @Override - public URL getUrl() { - return url; - } + @Override + public AzureApi getApi() { + return api; + } - @Override - public - Multimap getQueryParameters() { - return Multimaps.unmodifiableMultimap(queryParameters); - } + @Override + public URL getUrl() { + return url; + } - @Override - public Map getHeaders() { - return Collections.unmodifiableMap(headers); - } + @Override + public Multimap getQueryParameters() { + return Multimaps.unmodifiableMultimap(queryParameters); + } - @Override - public Optional getBody() { - return Optional.ofNullable(body); - } + @Override + public Map getHeaders() { + return Collections.unmodifiableMap(headers); + } + @Override + public Optional getBody() { + return Optional.ofNullable(body); + } } diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResponseInformation.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResponseInformation.java index 5459430..4a24c0c 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResponseInformation.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResponseInformation.java @@ -1,41 +1,36 @@ package tech.brenoepic.at4j.util.rest; - -import tech.brenoepic.at4j.AzureApi; - import java.util.Optional; +import tech.brenoepic.at4j.AzureApi; -/** - * Some information about a rest request response. - */ +/** Some information about a rest request response. */ public interface RestRequestResponseInformation { - /** - * Gets the azure api instance which created the request. - * - * @return The responsible azure api instance. - */ - AzureApi getApi(); - - /** - * Gets the request which this response answered. - * - * @return The request which this response answered. - */ - RestRequestInformation getRequest(); - - /** - * Gets the response code of the response. - * - * @return The response code of the response. - */ - int getCode(); - - /** - * Gets the body of the response as string. - * - * @return The body of the response. - */ - Optional getBody(); - -} \ No newline at end of file + /** + * Gets the azure api instance which created the request. + * + * @return The responsible azure api instance. + */ + AzureApi getApi(); + + /** + * Gets the request which this response answered. + * + * @return The request which this response answered. + */ + RestRequestInformation getRequest(); + + /** + * Gets the response code of the response. + * + * @return The response code of the response. + */ + int getCode(); + + /** + * Gets the body of the response as string. + * + * @return The body of the response. + */ + Optional getBody(); +} diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResponseInformationImpl.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResponseInformationImpl.java index 117362c..db242a6 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResponseInformationImpl.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResponseInformationImpl.java @@ -1,55 +1,52 @@ package tech.brenoepic.at4j.util.rest; -import tech.brenoepic.at4j.AzureApi; - import java.util.Optional; +import tech.brenoepic.at4j.AzureApi; -/** - * The implementation of {@link RestRequestResponseInformation}. - */ +/** The implementation of {@link RestRequestResponseInformation}. */ public class RestRequestResponseInformationImpl implements RestRequestResponseInformation { - private final RestRequestInformation request; - private final RestRequestResult restRequestResult; - - /** - * Creates a new rest request response information. - * - * @param request The request which this response answered. - * @param restRequestResult The result of the response. - */ - public RestRequestResponseInformationImpl(RestRequestInformation request, RestRequestResult restRequestResult) { - this.request = request; - this.restRequestResult = restRequestResult; - } - - /** - * Gets the rest request result. - * - * @return The rest request result. - */ - public RestRequestResult getRestRequestResult() { - return restRequestResult; - } - - @Override - public AzureApi getApi() { - return getRequest().getApi(); - } - - @Override - public RestRequestInformation getRequest() { - return request; - } - - @Override - public int getCode() { - return restRequestResult.getResponse().code(); - } - - @Override - public Optional getBody() { - return restRequestResult.getStringBody(); - } - + private final RestRequestInformation request; + private final RestRequestResult restRequestResult; + + /** + * Creates a new rest request response information. + * + * @param request The request which this response answered. + * @param restRequestResult The result of the response. + */ + public RestRequestResponseInformationImpl( + RestRequestInformation request, RestRequestResult restRequestResult) { + this.request = request; + this.restRequestResult = restRequestResult; + } + + /** + * Gets the rest request result. + * + * @return The rest request result. + */ + public RestRequestResult getRestRequestResult() { + return restRequestResult; + } + + @Override + public AzureApi getApi() { + return getRequest().getApi(); + } + + @Override + public RestRequestInformation getRequest() { + return request; + } + + @Override + public int getCode() { + return restRequestResult.getResponse().code(); + } + + @Override + public Optional getBody() { + return restRequestResult.getStringBody(); + } } diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResult.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResult.java index b891e6c..129d934 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResult.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResult.java @@ -4,103 +4,97 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.NullNode; +import java.io.IOException; +import java.util.Optional; import okhttp3.Response; import okhttp3.ResponseBody; import org.apache.logging.log4j.Logger; import tech.brenoepic.at4j.util.logging.LoggerUtil; -import java.io.IOException; -import java.util.Optional; - -/** - * The result of a {@link RestRequest}. - */ +/** The result of a {@link RestRequest}. */ public class RestRequestResult { - /** - * The (logger) of this class. - */ - private static final Logger logger = LoggerUtil.getLogger(RestRequestResult.class); + /** The (logger) of this class. */ + private static final Logger logger = LoggerUtil.getLogger(RestRequestResult.class); - private final RestRequest request; - private final Response response; - private final ResponseBody body; - private final String stringBody; - private final JsonNode jsonBody; + private final RestRequest request; + private final Response response; + private final ResponseBody body; + private final String stringBody; + private final JsonNode jsonBody; - /** - * Creates a new RestRequestResult. - * - * @param request The request of the result. - * @param response The response of the RestRequest. - * @throws IOException Passed on from {@link ResponseBody#string()}. - */ - public RestRequestResult(RestRequest request, Response response) throws IOException { - this.request = request; - this.response = response; - this.body = response.body(); - if (body == null) { - stringBody = null; - jsonBody = NullNode.getInstance(); - } else { - stringBody = body.string(); - ObjectMapper mapper = request.getApi().getObjectMapper(); - JsonNode jsonBody; - try { - jsonBody = mapper.readTree(stringBody); - } catch (JsonParseException e) { - // This can happen if Azure sends garbage - logger.debug("Failed to parse json response", e); - jsonBody = null; - } - this.jsonBody = jsonBody == null ? NullNode.getInstance() : jsonBody; - } + /** + * Creates a new RestRequestResult. + * + * @param request The request of the result. + * @param response The response of the RestRequest. + * @throws IOException Passed on from {@link ResponseBody#string()}. + */ + public RestRequestResult(RestRequest request, Response response) throws IOException { + this.request = request; + this.response = response; + this.body = response.body(); + if (body == null) { + stringBody = null; + jsonBody = NullNode.getInstance(); + } else { + stringBody = body.string(); + ObjectMapper mapper = request.getApi().getObjectMapper(); + JsonNode jsonBody; + try { + jsonBody = mapper.readTree(stringBody); + } catch (JsonParseException e) { + // This can happen if Azure sends garbage + logger.debug("Failed to parse json response", e); + jsonBody = null; + } + this.jsonBody = jsonBody == null ? NullNode.getInstance() : jsonBody; } + } - /** - * Gets the {@link RestRequest} which belongs to this result. - * - * @return The Request which belongs to this result. - */ - public RestRequest getRequest() { - return request; - } + /** + * Gets the {@link RestRequest} which belongs to this result. + * + * @return The Request which belongs to this result. + */ + public RestRequest getRequest() { + return request; + } - /** - * Gets the response of the {@link RestRequest}. - * - * @return The response of the RestRequest. - */ - public Response getResponse() { - return response; - } + /** + * Gets the response of the {@link RestRequest}. + * + * @return The response of the RestRequest. + */ + public Response getResponse() { + return response; + } - /** - * Gets the body of the response. - * - * @return The body of the response. - */ - public Optional getBody() { - return Optional.ofNullable(body); - } + /** + * Gets the body of the response. + * + * @return The body of the response. + */ + public Optional getBody() { + return Optional.ofNullable(body); + } - /** - * Gets the string body of the response. - * - * @return The string body of the response. - */ - public Optional getStringBody() { - return Optional.ofNullable(stringBody); - } - - /** - * Gets the json body of the response. - * Returns a {@link NullNode} if the response had none body or the body is not in a valid json format. - * - * @return The json body of the response. - */ - public JsonNode getJsonBody() { - return jsonBody; - } + /** + * Gets the string body of the response. + * + * @return The string body of the response. + */ + public Optional getStringBody() { + return Optional.ofNullable(stringBody); + } + /** + * Gets the json body of the response. Returns a {@link NullNode} if the response had none body or + * the body is not in a valid json format. + * + * @return The json body of the response. + */ + public JsonNode getJsonBody() { + return jsonBody; + } } diff --git a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResultErrorCode.java b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResultErrorCode.java index ca1e788..4a5a8f7 100644 --- a/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResultErrorCode.java +++ b/src/main/java/tech/brenoepic/at4j/util/rest/RestRequestResultErrorCode.java @@ -1,171 +1,325 @@ package tech.brenoepic.at4j.util.rest; - -import tech.brenoepic.at4j.core.exceptions.*; - import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; +import tech.brenoepic.at4j.core.exceptions.*; /** - * An enum with all rest request result codes as defined by - * Azure API Errors. - *
- * The error code is a 6-digit number combining the 3-digit HTTP status code followed by a 3-digit number to further categorize the error. + * An enum with all rest request result codes as defined by Azure + * API Errors.
+ * The error code is a 6-digit number combining the 3-digit HTTP status code followed by a + * 3-digit number to further categorize the error. */ public enum RestRequestResultErrorCode { + TARGET_LANGUAGE_NOT_VALID( + 400036, + "The target language is not valid or target language field is missing", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + BODY_REQUEST_NOT_VALID_JSON( + 400074, + "The body of the request is not valid JSON.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + REQUEST_INPUT_INVALID( + 400000, + "One of the request inputs isn't valid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + SCOPE_PARAMETER_INVALID( + 400001, + "The \"scope\" parameter is invalid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + CATEGORY_PARAMETER_INVALID( + 400002, + "The \"category\" parameter is invalid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + LANGUAGE_SPECIFIER_INVALID( + 400003, + "A language specifier is missing or invalid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + TARGET_SCRIPT_SPECIFIER_INVALID( + 400004, + "A target script specifier (\"To script\") is missing or invalid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + INPUT_TEXT_INVALID( + 400005, + "An input text is missing or invalid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + LANGUAGE_SCRIPT_COMBINATION_INVALID( + 400006, + "The combination of language and script isn't valid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + SOURCE_SCRIPT_SPECIFIER_INVALID( + 400018, + "A source script specifier (\"From script\") is missing or invalid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + SPECIFIED_LANGUAGE_UNSUPPORTED( + 400019, + "One of the specified languages isn't supported.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + INPUT_TEXT_ARRAY_ELEMENT_INVALID( + 400020, + "One of the elements in the array of input text isn't valid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + API_VERSION_PARAMETER_INVALID( + 400021, + "The API version parameter is missing or invalid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + SPECIFIED_LANGUAGE_PAIR_INVALID( + 400023, + "One of the specified language pair isn't valid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + SOURCE_LANGUAGE_INVALID( + 400035, + "The source language (\"From\" field) isn't valid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + OPTIONS_FIELD_INVALID( + 400042, + "One of the options specified (\"Options\" field) isn't valid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + CLIENT_TRACE_ID_INVALID( + 400043, + "The client trace ID (ClientTraceId field or X-ClientTranceId header) is missing or invalid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + INPUT_TEXT_TOO_LONG( + 400050, + "The input text is too long. View request limits.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + TRANSLATION_PARAMETER_INVALID( + 400064, + "The \"translation\" parameter is missing or invalid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + TARGET_SCRIPTS_NOT_MATCH_TARGET_LANGUAGES( + 400070, + "The number of target scripts (ToScript parameter) doesn't match the number of target" + + " languages (To parameter).", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + TEXT_TYPE_INVALID( + 400071, + "The value isn't valid for TextType.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + INPUT_TEXT_ARRAY_TOO_MANY_ELEMENTS( + 400072, + "The array of input text has too many elements.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + SCRIPT_PARAMETER_INVALID( + 400073, + "The script parameter isn't valid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + LANGUAGE_PAIR_CATEGORY_COMBINATION_INVALID( + 400075, + "The language pair and category combination isn't valid.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + REQUEST_SIZE_EXCEEDED( + 400077, + "The maximum request size has been exceeded. View request limits.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + CUSTOM_SYSTEM_NOT_EXIST( + 400079, + "The custom system requested for translation between from and to language doesn't exist.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + TRANSLITERATION_NOT_SUPPORTED( + 400080, + "Transliteration isn't supported for the language or script.", + BadRequestException::new, + RestRequestHttpResponseCode.BAD_REQUEST), + REQUEST_NOT_AUTHORIZED( + 401000, + "The request isn't authorized because credentials are missing or invalid.", + UnauthorizedException::new, + RestRequestHttpResponseCode.UNAUTHORIZED), + WRONG_CREDENTIALS_PROVIDED( + 401015, + "The credentials provided are for the Speech API. This request requires credentials for the" + + " Text API. Use a subscription to Translator.", + UnauthorizedException::new, + RestRequestHttpResponseCode.UNAUTHORIZED), + OPERATION_NOT_ALLOWED( + 403000, + "The operation isn't allowed.", + ForbiddenException::new, + RestRequestHttpResponseCode.FORBIDDEN), + FREE_QUOTA_EXCEEDED( + 403001, + "The operation isn't allowed because the subscription has exceeded its free quota.", + ForbiddenException::new, + RestRequestHttpResponseCode.FORBIDDEN), + REQUEST_METHOD_NOT_SUPPORTED( + 405000, + "The request method isn't supported for the requested resource.", + MethodNotAllowedException::new, + RestRequestHttpResponseCode.METHOD_NOT_ALLOWED), + TRANSLATION_SYSTEM_BEING_PREPARED( + 408001, + "The translation system requested is being prepared. Retry in a few minutes.", + RequestTimeoutException::new, + RestRequestHttpResponseCode.REQUEST_TIMEOUT), + REQUEST_TIMED_OUT( + 408002, + "Request timed out waiting on incoming stream. The client didn't produce a request within the" + + " time that the server was prepared to wait. The client may repeat the request without" + + " modifications at any later time.", + RequestTimeoutException::new, + RestRequestHttpResponseCode.REQUEST_TIMEOUT), + CONTENT_TYPE_HEADER_INVALID( + 415000, + "The Content-Type header is missing or invalid.", + UnsupportedMediaTypeException::new, + RestRequestHttpResponseCode.UNSUPPORTED_MEDIA_TYPE), + REQUEST_LIMITS_EXCEEDED( + 429000, "The server rejected the request because the client has exceeded request limits."), + UNEXPECTED_ERROR_OCCURRED( + 500000, + "An unexpected error occurred. If the error persists, report it with date/time of error," + + " request identifier from response header X-RequestId, and client identifier from" + + " request header X-ClientTraceId.", + InternalServerErrorException::new, + RestRequestHttpResponseCode.INTERNAL_SERVER_ERROR), + SERVICE_TEMPORARILY_UNAVAILABLE( + 503000, + "Service is temporarily unavailable. Retry. If the error persists, report it with date/time" + + " of error, request identifier from response header X-RequestId, and client identifier" + + " from request header X-ClientTraceId.", + ServiceUnavailableException::new, + RestRequestHttpResponseCode.SERVICE_UNAVAILABLE); + ; - TARGET_LANGUAGE_NOT_VALID(400036, - "The target language is not valid or target language field is missing", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - BODY_REQUEST_NOT_VALID_JSON(400074, - "The body of the request is not valid JSON.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - REQUEST_INPUT_INVALID(400000, "One of the request inputs isn't valid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - SCOPE_PARAMETER_INVALID(400001, "The \"scope\" parameter is invalid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - CATEGORY_PARAMETER_INVALID(400002, "The \"category\" parameter is invalid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - LANGUAGE_SPECIFIER_INVALID(400003, "A language specifier is missing or invalid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - TARGET_SCRIPT_SPECIFIER_INVALID(400004, "A target script specifier (\"To script\") is missing or invalid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - INPUT_TEXT_INVALID(400005, "An input text is missing or invalid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - LANGUAGE_SCRIPT_COMBINATION_INVALID(400006, "The combination of language and script isn't valid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - SOURCE_SCRIPT_SPECIFIER_INVALID(400018, "A source script specifier (\"From script\") is missing or invalid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - SPECIFIED_LANGUAGE_UNSUPPORTED(400019, "One of the specified languages isn't supported.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - INPUT_TEXT_ARRAY_ELEMENT_INVALID(400020, "One of the elements in the array of input text isn't valid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - API_VERSION_PARAMETER_INVALID(400021, "The API version parameter is missing or invalid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - SPECIFIED_LANGUAGE_PAIR_INVALID(400023, "One of the specified language pair isn't valid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - SOURCE_LANGUAGE_INVALID(400035, "The source language (\"From\" field) isn't valid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - OPTIONS_FIELD_INVALID(400042, "One of the options specified (\"Options\" field) isn't valid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - CLIENT_TRACE_ID_INVALID(400043, "The client trace ID (ClientTraceId field or X-ClientTranceId header) is missing or invalid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - INPUT_TEXT_TOO_LONG(400050, "The input text is too long. View request limits.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - TRANSLATION_PARAMETER_INVALID(400064, "The \"translation\" parameter is missing or invalid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - TARGET_SCRIPTS_NOT_MATCH_TARGET_LANGUAGES(400070, "The number of target scripts (ToScript parameter) doesn't match the number of target languages (To parameter).", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - TEXT_TYPE_INVALID(400071, "The value isn't valid for TextType.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - INPUT_TEXT_ARRAY_TOO_MANY_ELEMENTS(400072, "The array of input text has too many elements.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - SCRIPT_PARAMETER_INVALID(400073, "The script parameter isn't valid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - LANGUAGE_PAIR_CATEGORY_COMBINATION_INVALID(400075, "The language pair and category combination isn't valid.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - REQUEST_SIZE_EXCEEDED(400077, "The maximum request size has been exceeded. View request limits.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - CUSTOM_SYSTEM_NOT_EXIST(400079, "The custom system requested for translation between from and to language doesn't exist.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - TRANSLITERATION_NOT_SUPPORTED(400080, "Transliteration isn't supported for the language or script.", BadRequestException::new, RestRequestHttpResponseCode.BAD_REQUEST), - REQUEST_NOT_AUTHORIZED(401000, "The request isn't authorized because credentials are missing or invalid.", UnauthorizedException::new, RestRequestHttpResponseCode.UNAUTHORIZED), - WRONG_CREDENTIALS_PROVIDED(401015, "The credentials provided are for the Speech API. This request requires credentials for the Text API. Use a subscription to Translator.", UnauthorizedException::new, RestRequestHttpResponseCode.UNAUTHORIZED), - OPERATION_NOT_ALLOWED(403000, "The operation isn't allowed.", ForbiddenException::new, RestRequestHttpResponseCode.FORBIDDEN), - FREE_QUOTA_EXCEEDED(403001, "The operation isn't allowed because the subscription has exceeded its free quota.", ForbiddenException::new, RestRequestHttpResponseCode.FORBIDDEN), - REQUEST_METHOD_NOT_SUPPORTED(405000, "The request method isn't supported for the requested resource.", MethodNotAllowedException::new, RestRequestHttpResponseCode.METHOD_NOT_ALLOWED), - TRANSLATION_SYSTEM_BEING_PREPARED(408001, "The translation system requested is being prepared. Retry in a few minutes.", RequestTimeoutException::new, RestRequestHttpResponseCode.REQUEST_TIMEOUT), - REQUEST_TIMED_OUT(408002, "Request timed out waiting on incoming stream. The client didn't produce a request within the time that the server was prepared to wait. The client may repeat the request without modifications at any later time.", RequestTimeoutException::new, RestRequestHttpResponseCode.REQUEST_TIMEOUT), - CONTENT_TYPE_HEADER_INVALID(415000, "The Content-Type header is missing or invalid.", UnsupportedMediaTypeException::new, RestRequestHttpResponseCode.UNSUPPORTED_MEDIA_TYPE), - REQUEST_LIMITS_EXCEEDED(429000, "The server rejected the request because the client has exceeded request limits."), - UNEXPECTED_ERROR_OCCURRED(500000, "An unexpected error occurred. If the error persists, report it with date/time of error, request identifier from response header X-RequestId, and client identifier from request header X-ClientTraceId.", InternalServerErrorException::new, RestRequestHttpResponseCode.INTERNAL_SERVER_ERROR), - SERVICE_TEMPORARILY_UNAVAILABLE(503000, "Service is temporarily unavailable. Retry. If the error persists, report it with date/time of error, request identifier from response header X-RequestId, and client identifier from request header X-ClientTraceId.", ServiceUnavailableException::new, RestRequestHttpResponseCode.SERVICE_UNAVAILABLE); - ; - - /** - * A map for retrieving the enum instances by code. - */ - private static final Map instanceByCode; - - /** - * The actual numeric result code. - */ - private final int code; + /** A map for retrieving the enum instances by code. */ + private static final Map instanceByCode; - /** - * The textual meaning. - */ - private final String meaning; + /** The actual numeric result code. */ + private final int code; - /** - * The azure exception instantiate that produces instances to throw for this kind of result code. - */ - private final AzureExceptionInstantiator azureExceptionInstantiator; + /** The textual meaning. */ + private final String meaning; - /** - * The response code for which the given instantiating should be used. - */ - private final RestRequestHttpResponseCode responseCode; + /** + * The azure exception instantiate that produces instances to throw for this kind of result code. + */ + private final AzureExceptionInstantiator azureExceptionInstantiator; - static { - instanceByCode = Collections.unmodifiableMap( - Arrays.stream(values()) - .collect(Collectors.toMap(RestRequestResultErrorCode::getCode, Function.identity()))); - } + /** The response code for which the given instantiating should be used. */ + private final RestRequestHttpResponseCode responseCode; - /** - * Creates a new rest request result error code. - * - * @param code The actual numeric close code. - * @param meaning The textual meaning. - */ - RestRequestResultErrorCode(int code, String meaning) { - this(code, meaning, null, null); - } + static { + instanceByCode = + Collections.unmodifiableMap( + Arrays.stream(values()) + .collect( + Collectors.toMap(RestRequestResultErrorCode::getCode, Function.identity()))); + } - /** - * Creates a new rest request result error code. - * - * @param code The actual numeric close code. - * @param meaning The textual meaning. - * @param azureExceptionInstantiator The azure exception instantiator that produces - * instances to throw for this kind of result code. - * @param responseCode The response code for which the given instantiator should be used. - */ - RestRequestResultErrorCode(int code, String meaning, AzureExceptionInstantiator azureExceptionInstantiator, - RestRequestHttpResponseCode responseCode) { - this.code = code; - this.meaning = meaning; - this.azureExceptionInstantiator = azureExceptionInstantiator; - this.responseCode = responseCode; - } + /** + * Creates a new rest request result error code. + * + * @param code The actual numeric close code. + * @param meaning The textual meaning. + */ + RestRequestResultErrorCode(int code, String meaning) { + this(code, meaning, null, null); + } - /** - * Gets the rest request result error code by actual numeric result code. - * - * @param code The actual numeric close code. - * @param responseCode The response code. - * @return The web socket close code with the actual numeric result code. - */ - public static Optional fromCode(int code, RestRequestHttpResponseCode responseCode) { - return Optional.ofNullable(instanceByCode.get(code)) - .filter(errorCode -> errorCode.responseCode == responseCode); - } + /** + * Creates a new rest request result error code. + * + * @param code The actual numeric close code. + * @param meaning The textual meaning. + * @param azureExceptionInstantiator The azure exception instantiator that produces instances to + * throw for this kind of result code. + * @param responseCode The response code for which the given instantiator should be used. + */ + RestRequestResultErrorCode( + int code, + String meaning, + AzureExceptionInstantiator azureExceptionInstantiator, + RestRequestHttpResponseCode responseCode) { + this.code = code; + this.meaning = meaning; + this.azureExceptionInstantiator = azureExceptionInstantiator; + this.responseCode = responseCode; + } - /** - * Gets the actual numeric result code. - * - * @return The actual numeric result code. - */ - public int getCode() { - return code; - } + /** + * Gets the rest request result error code by actual numeric result code. + * + * @param code The actual numeric close code. + * @param responseCode The response code. + * @return The web socket close code with the actual numeric result code. + */ + public static Optional fromCode( + int code, RestRequestHttpResponseCode responseCode) { + return Optional.ofNullable(instanceByCode.get(code)) + .filter(errorCode -> errorCode.responseCode == responseCode); + } - /** - * Gets the textual meaning. - * - * @return The textual meaning. - */ - public String getMeaning() { - return meaning; - } + /** + * Gets the actual numeric result code. + * + * @return The actual numeric result code. + */ + public int getCode() { + return code; + } - /** - * Gets the azure exception to throw for this kind of result code. - * - * @param origin The origin of the exception. - * @param message The message of the exception. - * @param request The information about the request. - * @param response The information about the response. - * @return The azure exception to throw for this kind of result code. - */ - public Optional getAzureException(Exception origin, String message, - RestRequestInformation request, - RestRequestResponseInformation response) { - return Optional.ofNullable(azureExceptionInstantiator) - .map(instantiate -> instantiate.createInstance(origin, message, request, response)) - .filter(exception -> RestRequestHttpResponseCode.fromAzureExceptionClass(exception.getClass()) - .map(RestRequestHttpResponseCode::getCode) - .map(mapCode -> mapCode == response.getCode()) - .orElse(true)); - } + /** + * Gets the textual meaning. + * + * @return The textual meaning. + */ + public String getMeaning() { + return meaning; + } + /** + * Gets the azure exception to throw for this kind of result code. + * + * @param origin The origin of the exception. + * @param message The message of the exception. + * @param request The information about the request. + * @param response The information about the response. + * @return The azure exception to throw for this kind of result code. + */ + public Optional getAzureException( + Exception origin, + String message, + RestRequestInformation request, + RestRequestResponseInformation response) { + return Optional.ofNullable(azureExceptionInstantiator) + .map(instantiate -> instantiate.createInstance(origin, message, request, response)) + .filter( + exception -> + RestRequestHttpResponseCode.fromAzureExceptionClass(exception.getClass()) + .map(RestRequestHttpResponseCode::getCode) + .map(mapCode -> mapCode == response.getCode()) + .orElse(true)); + } } diff --git a/src/test/java/tech/brenoepic/at4j/AzureApiTest.java b/src/test/java/tech/brenoepic/at4j/AzureApiTest.java index 62305eb..9457f9b 100644 --- a/src/test/java/tech/brenoepic/at4j/AzureApiTest.java +++ b/src/test/java/tech/brenoepic/at4j/AzureApiTest.java @@ -1,5 +1,11 @@ package tech.brenoepic.at4j; +import static org.junit.Assert.*; + +import java.util.Collection; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; import okhttp3.OkHttpClient; import org.junit.Test; import tech.brenoepic.at4j.azure.BaseURL; @@ -8,95 +14,128 @@ import tech.brenoepic.at4j.data.request.TranslateParams; import tech.brenoepic.at4j.data.response.TranslationResponse; -import java.util.Collection; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; - -import static org.junit.Assert.*; - - public class AzureApiTest { - - - @Test - public void BuildNullKey() { - AzureApiBuilder builder = new AzureApiBuilder(); - assertThrows("Subscription key cannot be null", IllegalArgumentException.class, builder::build); - } - - @Test - public void BuildNullHttpClient() { - AzureApiBuilder builder = new AzureApiBuilder().setSubscriptionKey(""); - assertThrows("HTTP client cannot be null", IllegalArgumentException.class, builder::build); - } - - @Test - public void buildApi() { - AzureApi api = new AzureApiBuilder().setSubscriptionKey("test").setSubscriptionRegion("test").setOkHttpClient(new OkHttpClient()).build(); - assertNotNull(api); - api.getThreadPool().getExecutorService().shutdown(); - } - - - @Test - public void getLanguages() { - AzureApi api = new AzureApiBuilder().setBaseURL(BaseURL.GLOBAL).setSubscriptionKey("test").setSubscriptionRegion("test").setOkHttpClient(new OkHttpClient()).build(); - - CompletableFuture>> languages = api.getAvailableLanguages( new AvailableLanguagesParams().setSourceLanguage("en")); - languages.whenComplete((s, throwable) -> assertNull(throwable)); - assertNotNull(languages.join()); - api.getThreadPool().getExecutorService().shutdown(); - } - - @Test - public void getLanguagesEmptyKey() { - AzureApi api = new AzureApiBuilder().setBaseURL(BaseURL.GLOBAL).setSubscriptionKey("").setSubscriptionRegion("test").setOkHttpClient(new OkHttpClient()).build(); - - CompletableFuture>> languages = api.getAvailableLanguages(new AvailableLanguagesParams()); - languages.whenComplete((s, throwable) -> assertNull(throwable)); - api.getThreadPool().getExecutorService().shutdown(); - } - - @Test - public void getLanguagesEmptySourceLanguage() { - AzureApi api = new AzureApiBuilder().setBaseURL(BaseURL.GLOBAL).setSubscriptionKey("test").setSubscriptionRegion("test").setOkHttpClient(new OkHttpClient()).build(); - - CompletableFuture>> languages = api.getAvailableLanguages(new AvailableLanguagesParams()); - languages.whenComplete((s, throwable) -> assertNull(throwable)); - api.getThreadPool().getExecutorService().shutdown(); - } - - @Test - public void translateEmptyKey() { - AzureApi api = new AzureApiBuilder().setBaseURL(BaseURL.GLOBAL).setSubscriptionKey("").setSubscriptionRegion("test").setOkHttpClient(new OkHttpClient()).build(); - - TranslateParams params = new TranslateParams("test").setSourceLanguage("en").setTargetLanguages("pt"); - CompletableFuture> translation = api.translate(params); - assertThrows(CompletionException.class, translation::join); - api.getThreadPool().getExecutorService().shutdown(); - } - - @Test - public void translateEmptyText() { - AzureApi api = new AzureApiBuilder().setBaseURL(BaseURL.GLOBAL).setSubscriptionKey("test").setOkHttpClient(new OkHttpClient()).build(); - - TranslateParams params = new TranslateParams("").setSourceLanguage("en").setTargetLanguages("pt"); - CompletableFuture> translation = api.translate(params); - Optional tr = translation.join(); - tr.ifPresent(translations -> assertEquals(0, translations.getTranslations().size())); - api.getThreadPool().getExecutorService().shutdown(); - } - - @Test - public void translateEmptySourceLanguage() { - AzureApi api = new AzureApiBuilder().setBaseURL(BaseURL.GLOBAL).setSubscriptionKey("test").setOkHttpClient(new OkHttpClient()).build(); - - TranslateParams params = new TranslateParams("").setTargetLanguages("pt"); - CompletableFuture> translation = api.translate(params); - Optional tr = translation.join(); - tr.ifPresent(translations -> assertEquals(0, translations.getTranslations().size())); - api.getThreadPool().getExecutorService().shutdown(); - } + @Test + public void BuildNullKey() { + AzureApiBuilder builder = new AzureApiBuilder(); + assertThrows("Subscription key cannot be null", IllegalArgumentException.class, builder::build); + } + + @Test + public void BuildNullHttpClient() { + AzureApiBuilder builder = new AzureApiBuilder().setSubscriptionKey(""); + assertThrows("HTTP client cannot be null", IllegalArgumentException.class, builder::build); + } + + @Test + public void buildApi() { + AzureApi api = + new AzureApiBuilder() + .setSubscriptionKey("test") + .setSubscriptionRegion("test") + .setOkHttpClient(new OkHttpClient()) + .build(); + assertNotNull(api); + api.getThreadPool().getExecutorService().shutdown(); + } + + @Test + public void getLanguages() { + AzureApi api = + new AzureApiBuilder() + .setBaseURL(BaseURL.GLOBAL) + .setSubscriptionKey("test") + .setSubscriptionRegion("test") + .setOkHttpClient(new OkHttpClient()) + .build(); + + CompletableFuture>> languages = + api.getAvailableLanguages(new AvailableLanguagesParams().setSourceLanguage("en")); + languages.whenComplete((s, throwable) -> assertNull(throwable)); + assertNotNull(languages.join()); + api.getThreadPool().getExecutorService().shutdown(); + } + + @Test + public void getLanguagesEmptyKey() { + AzureApi api = + new AzureApiBuilder() + .setBaseURL(BaseURL.GLOBAL) + .setSubscriptionKey("") + .setSubscriptionRegion("test") + .setOkHttpClient(new OkHttpClient()) + .build(); + + CompletableFuture>> languages = + api.getAvailableLanguages(new AvailableLanguagesParams()); + languages.whenComplete((s, throwable) -> assertNull(throwable)); + api.getThreadPool().getExecutorService().shutdown(); + } + + @Test + public void getLanguagesEmptySourceLanguage() { + AzureApi api = + new AzureApiBuilder() + .setBaseURL(BaseURL.GLOBAL) + .setSubscriptionKey("test") + .setSubscriptionRegion("test") + .setOkHttpClient(new OkHttpClient()) + .build(); + + CompletableFuture>> languages = + api.getAvailableLanguages(new AvailableLanguagesParams()); + languages.whenComplete((s, throwable) -> assertNull(throwable)); + api.getThreadPool().getExecutorService().shutdown(); + } + + @Test + public void translateEmptyKey() { + AzureApi api = + new AzureApiBuilder() + .setBaseURL(BaseURL.GLOBAL) + .setSubscriptionKey("") + .setSubscriptionRegion("test") + .setOkHttpClient(new OkHttpClient()) + .build(); + + TranslateParams params = + new TranslateParams("test").setSourceLanguage("en").setTargetLanguages("pt"); + CompletableFuture> translation = api.translate(params); + assertThrows(CompletionException.class, translation::join); + api.getThreadPool().getExecutorService().shutdown(); + } + + @Test + public void translateEmptyText() { + AzureApi api = + new AzureApiBuilder() + .setBaseURL(BaseURL.GLOBAL) + .setSubscriptionKey("test") + .setOkHttpClient(new OkHttpClient()) + .build(); + + TranslateParams params = + new TranslateParams("").setSourceLanguage("en").setTargetLanguages("pt"); + CompletableFuture> translation = api.translate(params); + Optional tr = translation.join(); + tr.ifPresent(translations -> assertEquals(0, translations.getTranslations().size())); + api.getThreadPool().getExecutorService().shutdown(); + } + + @Test + public void translateEmptySourceLanguage() { + AzureApi api = + new AzureApiBuilder() + .setBaseURL(BaseURL.GLOBAL) + .setSubscriptionKey("test") + .setOkHttpClient(new OkHttpClient()) + .build(); + + TranslateParams params = new TranslateParams("").setTargetLanguages("pt"); + CompletableFuture> translation = api.translate(params); + Optional tr = translation.join(); + tr.ifPresent(translations -> assertEquals(0, translations.getTranslations().size())); + api.getThreadPool().getExecutorService().shutdown(); + } }